@praxisui/dynamic-form 10.0.0-rc.40 → 10.0.0-rc.42
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 +78 -4
- package/ai/component-registry.json +17 -5
- package/docs/custom-fields-enterprise-review.md +229 -0
- package/fesm2022/praxisui-dynamic-form.mjs +2080 -249
- package/package.json +8 -8
- package/src/lib/praxis-dynamic-form.json-api.md +16 -3
- package/types/praxisui-dynamic-form.d.ts +69 -11
- package/fesm2022/praxisui-dynamic-form-dynamic-form-agentic-authoring-turn-flow-w9V0aQ9B.mjs +0 -539
|
@@ -5,7 +5,7 @@ import { CommonModule } from '@angular/common';
|
|
|
5
5
|
import * as i2 from '@angular/common/http';
|
|
6
6
|
import { HttpHeaders, HttpErrorResponse, HttpContext } from '@angular/common/http';
|
|
7
7
|
import * as i1$3 from '@angular/forms';
|
|
8
|
-
import { ReactiveFormsModule, FormsModule,
|
|
8
|
+
import { FormGroup, ReactiveFormsModule, FormsModule, Validators } from '@angular/forms';
|
|
9
9
|
import * as i4 from '@angular/material/icon';
|
|
10
10
|
import { MatIconModule } from '@angular/material/icon';
|
|
11
11
|
import * as i3 from '@angular/material/button';
|
|
@@ -20,13 +20,13 @@ import * as i9 from '@angular/material/snack-bar';
|
|
|
20
20
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
21
21
|
import * as i19 from '@angular/material/badge';
|
|
22
22
|
import { MatBadgeModule } from '@angular/material/badge';
|
|
23
|
-
import { BehaviorSubject, map, Subscription, merge, of, timer, NEVER, EMPTY, defer, TimeoutError, Subject, firstValueFrom, throwError, combineLatest, forkJoin,
|
|
23
|
+
import { BehaviorSubject, map, Subscription, merge, of, timer, NEVER, EMPTY, defer, TimeoutError, Subject, Observable, firstValueFrom, throwError, combineLatest, forkJoin, race, from, debounceTime as debounceTime$1, takeUntil as takeUntil$1, catchError as catchError$1, defaultIfEmpty, take as take$1, switchMap as switchMap$1, finalize as finalize$1 } from 'rxjs';
|
|
24
24
|
import { filter, map as map$1, switchMap, take, timeout, throwIfEmpty, tap, catchError, ignoreElements, finalize, takeUntil, skip, debounceTime, startWith } from 'rxjs/operators';
|
|
25
25
|
import * as i1 from '@praxisui/core';
|
|
26
|
-
import { serializeEntityLookupValueForPayload, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, migrateFormLayoutRule, PraxisJsonLogicService, normalizeFormLayoutItems, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, formIdentityIssues, resolveHidden, resolveOrder, resolveSpan, projectGroupedCommandPartialRows, isPraxisRuntimeGlobalActionEffect, ASYNC_CONFIG_STORAGE, withFormConfigSections, createFieldLayoutItem, getFormLayoutFieldNames, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceDiscoveryService, GlobalActionService, SCHEMA_METADATA_CLIENT_OPTIONS, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, readStrongResourceEtag, ApiEndpoint, mapFieldDefinitionsToMetadata, reconcileFormConfig, applyLocalFormCustomizations, materializeFormLayoutFromMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, evaluateFieldAccess,
|
|
26
|
+
import { normalizeControlTypeKey, normalizeScalarArrayValue, serializeEntityLookupValueForPayload, PRAXIS_RUNTIME_FORM_VALUE_PROPOSAL_SCHEMA_VERSION, PraxisI18nService, PraxisIconButtonComponent, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, migrateFormLayoutRule, PraxisJsonLogicService, normalizeFormLayoutItems, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, formIdentityIssues, resolveHidden, resolveOrder, resolveSpan, projectGroupedCommandPartialRows, isPraxisRuntimeGlobalActionEffect, ASYNC_CONFIG_STORAGE, withFormConfigSections, createFieldLayoutItem, getFormLayoutFieldNames, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceDiscoveryService, GlobalActionService, SCHEMA_METADATA_CLIENT_OPTIONS, PraxisRuntimeFormValueSessionJournal, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, readStrongResourceEtag, ApiEndpoint, mapFieldDefinitionsToMetadata, reconcileFormConfig, applyLocalFormCustomizations, materializeFormLayoutFromMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, evaluateFieldAccess, normalizePraxisEffectPolicy, buildPraxisEffectDistinctKey, getFormColumnFieldNames, resolveGroupedCommandPartialRowSpans, resolveOffset, buildSchemaIdStorageKeySegment, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, DEFAULT_SCHEMA_REQUEST_TIMEOUT_MS, normalizeReactiveDeterminations, previewRuntimeFormValueProposal, applyRuntimeFormValueProposal, undoRuntimeFormValueApply, instanceKeyFor, CONNECTION_STORAGE, API_URL, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, EmptyStateCardComponent, GenericCrudService, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, hasSemanticFieldCalibrationDiff, calibrateFieldMetadataFromSemantics, canOrganizeFormLayoutBySemantics, organizeFormLayoutBySemantics, isRequiredGlobalActionPayloadMissing, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, IconPickerService, validateGlobalActionRefs, normalizeFormMetadata, mapCatalogFieldsToMetadata, uiLayoutJsonIdentity, DynamicFormService, projectComponentAuthoringManifest, cloneBoundedUiLayoutJsonDocument, derivePageChildRuntimeId } from '@praxisui/core';
|
|
27
27
|
import * as i1$1 from '@praxisui/dynamic-fields';
|
|
28
28
|
import { getControlTypeCatalog, SelectOptionRegistry, ConfirmDialogComponent, DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
|
|
29
|
-
import { BaseAiAdapter, AgenticAuthoringTurnClientService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnOrchestratorService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
|
|
29
|
+
import { withAuthoringScopePolicy, BaseAiAdapter, AgenticAuthoringTurnClientService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnOrchestratorService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
|
|
30
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';
|
|
@@ -63,6 +63,76 @@ import { MatExpansionModule } from '@angular/material/expansion';
|
|
|
63
63
|
import { MatListModule } from '@angular/material/list';
|
|
64
64
|
import { CascadeRulesService, CascadeManagerTabComponent } from '@praxisui/metadata-editor';
|
|
65
65
|
|
|
66
|
+
/** Internal record paths for form values; array items are handled by their own schema. */
|
|
67
|
+
// constructor/prototype can be legitimate own data keys. Traversal below never
|
|
68
|
+
// follows inherited values, and computed spread writes create own properties.
|
|
69
|
+
const unsafeSegments = new Set(['__proto__']);
|
|
70
|
+
function segmentsFor(path) {
|
|
71
|
+
const segments = path.split('.');
|
|
72
|
+
return segments.every(segment => segment.length > 0 && !unsafeSegments.has(segment))
|
|
73
|
+
? segments
|
|
74
|
+
: undefined;
|
|
75
|
+
}
|
|
76
|
+
function isRecord$2(value) {
|
|
77
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
78
|
+
return false;
|
|
79
|
+
const prototype = Object.getPrototypeOf(value);
|
|
80
|
+
return prototype === Object.prototype || prototype === null;
|
|
81
|
+
}
|
|
82
|
+
function hasNestedPath(value, path) {
|
|
83
|
+
const segments = segmentsFor(path);
|
|
84
|
+
if (!segments)
|
|
85
|
+
return false;
|
|
86
|
+
let current = value;
|
|
87
|
+
for (const segment of segments) {
|
|
88
|
+
if (!isRecord$2(current) || !Object.prototype.hasOwnProperty.call(current, segment))
|
|
89
|
+
return false;
|
|
90
|
+
current = current[segment];
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
function getNestedPath(value, path) {
|
|
95
|
+
if (!hasNestedPath(value, path))
|
|
96
|
+
return undefined;
|
|
97
|
+
let current = value;
|
|
98
|
+
for (const segment of path.split('.')) {
|
|
99
|
+
current = current[segment];
|
|
100
|
+
}
|
|
101
|
+
return current;
|
|
102
|
+
}
|
|
103
|
+
/** Copies only the record ancestors; never traverses inherited or unsafe properties. */
|
|
104
|
+
function setNestedPath(value, path, next) {
|
|
105
|
+
const segments = segmentsFor(path);
|
|
106
|
+
if (!segments)
|
|
107
|
+
return value;
|
|
108
|
+
const write = (record, index) => {
|
|
109
|
+
const key = segments[index];
|
|
110
|
+
if (index === segments.length - 1)
|
|
111
|
+
return { ...record, [key]: next };
|
|
112
|
+
const child = Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
|
|
113
|
+
if (child !== undefined && !isRecord$2(child))
|
|
114
|
+
return record;
|
|
115
|
+
const updated = write(child ?? {}, index + 1);
|
|
116
|
+
return { ...record, [key]: updated };
|
|
117
|
+
};
|
|
118
|
+
return write(value, 0);
|
|
119
|
+
}
|
|
120
|
+
function deleteNestedPath(value, path) {
|
|
121
|
+
if (!hasNestedPath(value, path))
|
|
122
|
+
return value;
|
|
123
|
+
const segments = path.split('.');
|
|
124
|
+
const remove = (record, index) => {
|
|
125
|
+
const copy = { ...record };
|
|
126
|
+
const key = segments[index];
|
|
127
|
+
if (index === segments.length - 1)
|
|
128
|
+
delete copy[key];
|
|
129
|
+
else
|
|
130
|
+
copy[key] = remove(record[key], index + 1);
|
|
131
|
+
return copy;
|
|
132
|
+
};
|
|
133
|
+
return remove(value, 0);
|
|
134
|
+
}
|
|
135
|
+
|
|
66
136
|
const PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE = 'praxisDynamicForm';
|
|
67
137
|
const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
|
|
68
138
|
namespaces: {
|
|
@@ -101,6 +171,12 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
|
|
|
101
171
|
'config.emptyState.option.circle': 'Círculo',
|
|
102
172
|
'config.emptyState.option.soft': 'Suave',
|
|
103
173
|
'runtime.schemaRead.timeout': 'O carregamento dos campos excedeu o tempo limite. Tente novamente.',
|
|
174
|
+
'runtime.schemaRead.deniedTitle': 'Acesso ao formulário não autorizado',
|
|
175
|
+
'runtime.schemaRead.denied': 'Sua sessão não tem permissão para carregar este formulário. Verifique o acesso antes de continuar.',
|
|
176
|
+
'runtime.schemaRead.invalidTitle': 'Metadados do formulário inválidos',
|
|
177
|
+
'runtime.schemaRead.invalid': 'Os metadados recebidos não puderam ser validados. A configuração do servidor precisa ser corrigida antes de continuar.',
|
|
178
|
+
'runtime.schemaRead.contextRequiredTitle': 'Contexto de acesso não confirmado',
|
|
179
|
+
'runtime.schemaRead.contextRequired': 'Confirme o contexto de acesso da sessão antes de carregar este formulário.',
|
|
104
180
|
'runtime.entityRead.loading': 'Atualizando dados do registro…',
|
|
105
181
|
'runtime.entityRead.error': 'Não foi possível carregar os dados deste registro.',
|
|
106
182
|
'runtime.entityRead.retry': 'Tentar novamente',
|
|
@@ -111,6 +187,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
|
|
|
111
187
|
'runtime.configControls.reconcile': 'O schema do servidor mudou — reconciliar',
|
|
112
188
|
'runtime.configControls.disconnect': 'Desconectar da fonte de dados',
|
|
113
189
|
'layout.defaultSectionTitle': 'Informações',
|
|
190
|
+
'runtime.actionTarget.selectedRecord': 'Registro selecionado',
|
|
114
191
|
'actions.invalidRequired': 'Preencha os campos obrigatórios para continuar.',
|
|
115
192
|
'actions.invalidRequiredWithFields': 'Preencha: {{fields}}.',
|
|
116
193
|
'actions.submitErrorTitle': 'Erro ao salvar',
|
|
@@ -705,6 +782,12 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
|
|
|
705
782
|
'config.emptyState.option.circle': 'Circle',
|
|
706
783
|
'config.emptyState.option.soft': 'Soft',
|
|
707
784
|
'runtime.schemaRead.timeout': 'Loading the form fields timed out. Try again.',
|
|
785
|
+
'runtime.schemaRead.deniedTitle': 'Form access denied',
|
|
786
|
+
'runtime.schemaRead.denied': 'Your session does not have permission to load this form. Check access before continuing.',
|
|
787
|
+
'runtime.schemaRead.invalidTitle': 'Invalid form metadata',
|
|
788
|
+
'runtime.schemaRead.invalid': 'The received metadata could not be validated. The server configuration must be corrected before continuing.',
|
|
789
|
+
'runtime.schemaRead.contextRequiredTitle': 'Access context not confirmed',
|
|
790
|
+
'runtime.schemaRead.contextRequired': 'Confirm the session access context before loading this form.',
|
|
708
791
|
'runtime.entityRead.loading': 'Updating record details…',
|
|
709
792
|
'runtime.entityRead.error': 'Could not load this record’s details.',
|
|
710
793
|
'runtime.entityRead.retry': 'Try again',
|
|
@@ -720,6 +803,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
|
|
|
720
803
|
'runtime.configControls.reconcile': 'Server schema changed — reconcile',
|
|
721
804
|
'runtime.configControls.disconnect': 'Disconnect from data source',
|
|
722
805
|
'layout.defaultSectionTitle': 'Information',
|
|
806
|
+
'runtime.actionTarget.selectedRecord': 'Selected record',
|
|
723
807
|
'actions.invalidRequired': 'Complete the required fields to continue.',
|
|
724
808
|
'actions.invalidRequiredWithFields': 'Complete: {{fields}}.',
|
|
725
809
|
'actions.submitErrorTitle': 'Save error',
|
|
@@ -1484,29 +1568,82 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
1484
1568
|
}]
|
|
1485
1569
|
}], ctorParameters: () => [{ type: i1.DomainRuleService }] });
|
|
1486
1570
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1571
|
+
const temporalControlTypes = new Set([
|
|
1572
|
+
'DATE', 'DATE_PICKER', 'DATE_INPUT', 'DATE_RANGE', 'DATE_TIME_PICKER',
|
|
1573
|
+
'DATETIME_LOCAL_INPUT', 'DATE_TIME_RANGE', 'INLINE_DATE', 'INLINE_DATE_RANGE',
|
|
1574
|
+
]);
|
|
1575
|
+
const temporalDataTypes = new Set(['date', 'local-date', 'localdate', 'date-time', 'datetime', 'instant']);
|
|
1576
|
+
/** Converts legacy date tuples only where the existing field metadata declares a temporal value. */
|
|
1577
|
+
function normalizeDateArrays(data, fields) {
|
|
1578
|
+
return normalizeTemporalFieldValues(data, fields, value => value);
|
|
1579
|
+
}
|
|
1580
|
+
/** One private draft shared by hydration and submit; only declared temporal fields are transformed. */
|
|
1581
|
+
function normalizeTemporalFieldValues(data, fields, normalizeString) {
|
|
1582
|
+
const draft = cloneValue$1(data);
|
|
1583
|
+
normalizeRecord(draft, fields, normalizeString);
|
|
1584
|
+
return draft;
|
|
1585
|
+
}
|
|
1586
|
+
function normalizeRecord(draft, fields, normalizeString) {
|
|
1587
|
+
if (!draft || typeof draft !== 'object' || Array.isArray(draft) || draft instanceof Date)
|
|
1588
|
+
return;
|
|
1589
|
+
for (const field of fields) {
|
|
1590
|
+
if (!hasNestedPath(draft, field.name))
|
|
1591
|
+
continue;
|
|
1592
|
+
const value = getNestedPath(draft, field.name);
|
|
1593
|
+
const itemFields = field.array?.itemSchema?.fields;
|
|
1594
|
+
if (Array.isArray(value) && itemFields?.length) {
|
|
1595
|
+
value.forEach(item => normalizeRecord(item, itemFields, normalizeString));
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
if (!isTemporalField(field))
|
|
1599
|
+
continue;
|
|
1600
|
+
const normalized = normalizeTemporalValue(value, normalizeString);
|
|
1601
|
+
if (!field.name.includes('.')) {
|
|
1602
|
+
draft[field.name] = normalized;
|
|
1603
|
+
}
|
|
1604
|
+
else {
|
|
1605
|
+
// hasNestedPath admitted each own segment. All ancestors belong to the
|
|
1606
|
+
// private draft, so writing the leaf does not require copying the record.
|
|
1607
|
+
const boundary = field.name.lastIndexOf('.');
|
|
1608
|
+
const parent = getNestedPath(draft, field.name.slice(0, boundary));
|
|
1609
|
+
parent[field.name.slice(boundary + 1)] = normalized;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
function isTemporalField(field) {
|
|
1614
|
+
return temporalControlTypes.has(normalizeControlTypeKey(field.controlType)) ||
|
|
1615
|
+
temporalDataTypes.has(String(field.dataType ?? '').toLowerCase()) ||
|
|
1616
|
+
temporalDataTypes.has(String(field.format ?? '').toLowerCase());
|
|
1617
|
+
}
|
|
1618
|
+
function cloneValue$1(data) {
|
|
1619
|
+
if (data instanceof Date)
|
|
1620
|
+
return data;
|
|
1621
|
+
if (Array.isArray(data))
|
|
1622
|
+
return data.map(cloneValue$1);
|
|
1623
|
+
if (data && typeof data === 'object') {
|
|
1624
|
+
return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, cloneValue$1(value)]));
|
|
1625
|
+
}
|
|
1626
|
+
return data;
|
|
1627
|
+
}
|
|
1628
|
+
function normalizeTemporalValue(data, normalizeString) {
|
|
1493
1629
|
if (data instanceof Date) {
|
|
1494
1630
|
return data;
|
|
1495
1631
|
}
|
|
1496
1632
|
if (Array.isArray(data)) {
|
|
1497
1633
|
if (isDateArray(data)) {
|
|
1498
|
-
return formatDateArray(data);
|
|
1634
|
+
return normalizeString(formatDateArray(data));
|
|
1499
1635
|
}
|
|
1500
|
-
|
|
1636
|
+
for (let index = 0; index < data.length; index += 1)
|
|
1637
|
+
data[index] = normalizeTemporalValue(data[index], normalizeString);
|
|
1638
|
+
return data;
|
|
1501
1639
|
}
|
|
1502
1640
|
if (data && typeof data === 'object') {
|
|
1503
|
-
const result = {};
|
|
1504
1641
|
for (const [key, value] of Object.entries(data)) {
|
|
1505
|
-
|
|
1642
|
+
data[key] = normalizeTemporalValue(value, normalizeString);
|
|
1506
1643
|
}
|
|
1507
|
-
return
|
|
1644
|
+
return data;
|
|
1508
1645
|
}
|
|
1509
|
-
return data;
|
|
1646
|
+
return typeof data === 'string' ? normalizeString(data) : data;
|
|
1510
1647
|
}
|
|
1511
1648
|
function isDateArray(arr) {
|
|
1512
1649
|
if (arr.length < 3 || arr.length > 7)
|
|
@@ -1530,30 +1667,8 @@ function formatDateArray(arr) {
|
|
|
1530
1667
|
|
|
1531
1668
|
const ISO_LOCAL_DATETIME_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?$/;
|
|
1532
1669
|
const ISO_OFFSET_OR_Z_SUFFIX_PATTERN = /(Z|[+\-]\d{2}:\d{2})$/i;
|
|
1533
|
-
function normalizeSubmitPayload(data) {
|
|
1534
|
-
return
|
|
1535
|
-
}
|
|
1536
|
-
function normalizeTemporalStrings(value) {
|
|
1537
|
-
// Date-only fields are converted by the field-aware submit pipeline. Keep
|
|
1538
|
-
// native Date values intact here instead of treating them as generic records
|
|
1539
|
-
// (which would otherwise turn them into an empty object).
|
|
1540
|
-
if (value instanceof Date) {
|
|
1541
|
-
return value;
|
|
1542
|
-
}
|
|
1543
|
-
if (Array.isArray(value)) {
|
|
1544
|
-
return value.map((item) => normalizeTemporalStrings(item));
|
|
1545
|
-
}
|
|
1546
|
-
if (value && typeof value === 'object') {
|
|
1547
|
-
const normalized = {};
|
|
1548
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
1549
|
-
normalized[key] = normalizeTemporalStrings(nested);
|
|
1550
|
-
}
|
|
1551
|
-
return normalized;
|
|
1552
|
-
}
|
|
1553
|
-
if (typeof value === 'string') {
|
|
1554
|
-
return normalizeLocalDateTimeString(value);
|
|
1555
|
-
}
|
|
1556
|
-
return value;
|
|
1670
|
+
function normalizeSubmitPayload(data, fields) {
|
|
1671
|
+
return normalizeTemporalFieldValues(data, fields, normalizeLocalDateTimeString);
|
|
1557
1672
|
}
|
|
1558
1673
|
function normalizeLocalDateTimeString(value) {
|
|
1559
1674
|
const trimmed = String(value || '').trim();
|
|
@@ -1606,7 +1721,7 @@ function pad(value) {
|
|
|
1606
1721
|
}
|
|
1607
1722
|
|
|
1608
1723
|
function prepareSubmitPayload(rawValue, fieldMetadata, options = {}) {
|
|
1609
|
-
const normalized = normalizeSubmitPayload(rawValue);
|
|
1724
|
+
const normalized = normalizeSubmitPayload(rawValue, fieldMetadata ?? []);
|
|
1610
1725
|
if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) {
|
|
1611
1726
|
return normalized;
|
|
1612
1727
|
}
|
|
@@ -1654,17 +1769,35 @@ function shouldOmitByPolicy(policy, fieldName, dirtyFields, scopePath) {
|
|
|
1654
1769
|
}
|
|
1655
1770
|
}
|
|
1656
1771
|
function filterRecordForSubmit(value, fields, dirtyFields, scopePath) {
|
|
1657
|
-
|
|
1772
|
+
let payload = { ...value };
|
|
1658
1773
|
for (const field of fields) {
|
|
1774
|
+
const isNested = field.name.includes('.');
|
|
1775
|
+
if (isNested && !hasNestedPath(payload, field.name))
|
|
1776
|
+
continue;
|
|
1659
1777
|
if (shouldOmitFieldFromSubmit(field, dirtyFields, scopePath)) {
|
|
1660
|
-
|
|
1778
|
+
if (isNested)
|
|
1779
|
+
payload = deleteNestedPath(payload, field.name);
|
|
1780
|
+
else
|
|
1781
|
+
delete payload[field.name];
|
|
1661
1782
|
continue;
|
|
1662
1783
|
}
|
|
1663
|
-
const fieldValue =
|
|
1784
|
+
const fieldValue = isNested
|
|
1785
|
+
? getNestedPath(payload, field.name)
|
|
1786
|
+
: Object.prototype.hasOwnProperty.call(payload, field.name) ? payload[field.name] : undefined;
|
|
1664
1787
|
const fieldPath = buildScopedFieldPath(field.name, scopePath);
|
|
1665
|
-
|
|
1666
|
-
if (shouldOmitEmptyOptionalField(field,
|
|
1667
|
-
|
|
1788
|
+
const normalizedValue = normalizeFieldValueForSubmit(field, fieldValue, dirtyFields, fieldPath);
|
|
1789
|
+
if (shouldOmitEmptyOptionalField(field, normalizedValue, dirtyFields, scopePath)) {
|
|
1790
|
+
if (isNested)
|
|
1791
|
+
payload = deleteNestedPath(payload, field.name);
|
|
1792
|
+
else
|
|
1793
|
+
delete payload[field.name];
|
|
1794
|
+
}
|
|
1795
|
+
else if (isNested) {
|
|
1796
|
+
payload = setNestedPath(payload, field.name, normalizedValue);
|
|
1797
|
+
}
|
|
1798
|
+
else {
|
|
1799
|
+
// The root is already a private draft; do not copy every flat field for each write.
|
|
1800
|
+
payload[field.name] = normalizedValue;
|
|
1668
1801
|
}
|
|
1669
1802
|
}
|
|
1670
1803
|
return payload;
|
|
@@ -1681,6 +1814,12 @@ function normalizeFieldValueForSubmit(field, value, dirtyFields, fieldPath) {
|
|
|
1681
1814
|
*/
|
|
1682
1815
|
function normalizeFieldValueForRequestPayload(field, value) {
|
|
1683
1816
|
if (field) {
|
|
1817
|
+
if (field.items) {
|
|
1818
|
+
const result = normalizeScalarArrayValue(value, field.items);
|
|
1819
|
+
if (!result.valid)
|
|
1820
|
+
throw new TypeError(`Invalid scalar array value for field: ${field.name}`);
|
|
1821
|
+
value = result.value;
|
|
1822
|
+
}
|
|
1684
1823
|
const normalizedDateValue = normalizeDateOnlyFieldValueForSubmit(field, value);
|
|
1685
1824
|
return normalizeEntityLookupValueForSubmit(field, normalizedDateValue);
|
|
1686
1825
|
}
|
|
@@ -1717,8 +1856,8 @@ function isDateOnlyField(field) {
|
|
|
1717
1856
|
if (dataType === 'date') {
|
|
1718
1857
|
return true;
|
|
1719
1858
|
}
|
|
1720
|
-
const controlType =
|
|
1721
|
-
return controlType === '
|
|
1859
|
+
const controlType = normalizeControlTypeKey(field.controlType);
|
|
1860
|
+
return controlType === 'DATE' || controlType === 'DATE_PICKER' || controlType === 'DATE_INPUT';
|
|
1722
1861
|
}
|
|
1723
1862
|
function isIsoDate(value) {
|
|
1724
1863
|
return /^\d{4}-\d{2}-\d{2}$/.test(value);
|
|
@@ -1910,21 +2049,35 @@ class ReactiveDeterminationRuntimeService {
|
|
|
1910
2049
|
return;
|
|
1911
2050
|
}
|
|
1912
2051
|
composite.add(this.claimTargets(form, targetControls));
|
|
2052
|
+
const isOnInitMode = definition.trigger.mode === 'on-init' ||
|
|
2053
|
+
definition.trigger.mode === 'on-init-and-change';
|
|
2054
|
+
const isOnChangeMode = definition.trigger.mode === 'on-change' ||
|
|
2055
|
+
definition.trigger.mode === 'on-init-and-change';
|
|
1913
2056
|
const triggerControlSet = new Set(triggerControls);
|
|
1914
2057
|
const targetControlSet = new Set(targetControls);
|
|
1915
|
-
const
|
|
1916
|
-
const
|
|
1917
|
-
...new Set([...
|
|
1918
|
-
|
|
2058
|
+
const upstreamInputControls = this.resolveControls(form, [...upstreamInputPaths]);
|
|
2059
|
+
const dependencyObservedControls = isOnChangeMode
|
|
2060
|
+
? [...new Set([...triggerControls, ...inputControls])]
|
|
2061
|
+
: [...new Set(upstreamInputControls)];
|
|
2062
|
+
const directlyObservedControls = isOnChangeMode
|
|
2063
|
+
? [...new Set([...dependencyObservedControls, ...targetControls])]
|
|
2064
|
+
: [...new Set(targetControls)];
|
|
1919
2065
|
const committedControls$ = this.getOrCreateCommittedControls(form);
|
|
1920
2066
|
const changes$ = merge(of({
|
|
1921
|
-
shouldExecute:
|
|
2067
|
+
shouldExecute: isOnInitMode
|
|
2068
|
+
? true
|
|
2069
|
+
: triggerControls.some((control) => hasMeaningfulSourceValue(control.value)),
|
|
1922
2070
|
initial: true,
|
|
1923
2071
|
}), ...directlyObservedControls.flatMap((control) => [control.valueChanges, control.statusChanges].map((changes) => changes.pipe(filter(() => !this.publishingCommitByForm.has(form)), map$1(() => ({
|
|
1924
|
-
shouldExecute: triggerControlSet.has(control) ||
|
|
2072
|
+
shouldExecute: (isOnChangeMode && triggerControlSet.has(control)) ||
|
|
2073
|
+
targetControlSet.has(control),
|
|
1925
2074
|
initial: false,
|
|
1926
2075
|
}))))), committedControls$.pipe(filter((committedControls) => dependencyObservedControls.some((control) => committedControls.has(control))), map$1((committedControls) => ({
|
|
1927
|
-
shouldExecute:
|
|
2076
|
+
shouldExecute: (isOnChangeMode &&
|
|
2077
|
+
triggerControls.some((control) => committedControls.has(control))) ||
|
|
2078
|
+
(upstreamInputControls.some((control) => committedControls.has(control)) &&
|
|
2079
|
+
(isOnInitMode ||
|
|
2080
|
+
triggerControls.some((control) => hasMeaningfulSourceValue(control.value)))),
|
|
1928
2081
|
initial: false,
|
|
1929
2082
|
}))));
|
|
1930
2083
|
const determinationSubscription = changes$
|
|
@@ -1972,7 +2125,7 @@ class ReactiveDeterminationRuntimeService {
|
|
|
1972
2125
|
publishEvent(this.event(definition, 'error', signal.correlationId, 0, 'request-binding-invalid'));
|
|
1973
2126
|
return EMPTY;
|
|
1974
2127
|
}
|
|
1975
|
-
const currentOutputFingerprint = this.buildOutputFingerprint(form, definition);
|
|
2128
|
+
const currentOutputFingerprint = this.buildOutputFingerprint(form, definition, fieldMetadata);
|
|
1976
2129
|
if (invocation.fingerprint === lastSuccessfulFingerprint &&
|
|
1977
2130
|
currentOutputFingerprint !== null &&
|
|
1978
2131
|
currentOutputFingerprint === lastSuccessfulOutputFingerprint) {
|
|
@@ -1993,7 +2146,7 @@ class ReactiveDeterminationRuntimeService {
|
|
|
1993
2146
|
this.commit(form, commit);
|
|
1994
2147
|
this.satisfyGeneration(form, determinationKey, signal.generation);
|
|
1995
2148
|
lastSuccessfulFingerprint = invocation.fingerprint;
|
|
1996
|
-
lastSuccessfulOutputFingerprint = this.buildOutputFingerprint(form, definition);
|
|
2149
|
+
lastSuccessfulOutputFingerprint = this.buildOutputFingerprint(form, definition, fieldMetadata);
|
|
1997
2150
|
publishEvent(this.event(definition, 'success', signal.correlationId, Date.now() - startedAt, undefined, commit.map((entry) => entry.targetPath)));
|
|
1998
2151
|
}), catchError((error) => {
|
|
1999
2152
|
if (this.isCurrentGeneration(form, determinationKey, signal.generation)) {
|
|
@@ -2109,13 +2262,15 @@ class ReactiveDeterminationRuntimeService {
|
|
|
2109
2262
|
}
|
|
2110
2263
|
return entries;
|
|
2111
2264
|
}
|
|
2112
|
-
buildOutputFingerprint(form, definition) {
|
|
2265
|
+
buildOutputFingerprint(form, definition, fieldMetadata) {
|
|
2113
2266
|
const values = [];
|
|
2114
2267
|
for (const binding of definition.outputs) {
|
|
2115
|
-
const
|
|
2268
|
+
const segments = jsonPointerSegments(binding.fieldPath);
|
|
2269
|
+
const control = form.get(segments);
|
|
2116
2270
|
if (!control)
|
|
2117
2271
|
return null;
|
|
2118
|
-
|
|
2272
|
+
const field = resolveFieldMetadataForSegments(fieldMetadata, segments);
|
|
2273
|
+
values.push(normalizeFieldValueForRequestPayload(field, control.value));
|
|
2119
2274
|
}
|
|
2120
2275
|
return stableFingerprint(values);
|
|
2121
2276
|
}
|
|
@@ -2377,6 +2532,878 @@ function createCorrelationId() {
|
|
|
2377
2532
|
return `reactive-determination-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
2378
2533
|
}
|
|
2379
2534
|
|
|
2535
|
+
class DynamicFormAgenticAuthoringTurnFlow {
|
|
2536
|
+
adapter;
|
|
2537
|
+
turnClient;
|
|
2538
|
+
mode = 'agentic-authoring';
|
|
2539
|
+
constructor(adapter, turnClient) {
|
|
2540
|
+
this.adapter = adapter;
|
|
2541
|
+
this.turnClient = turnClient;
|
|
2542
|
+
}
|
|
2543
|
+
submit(request) {
|
|
2544
|
+
if (request.action?.kind === 'runtime-form-value-undo' ||
|
|
2545
|
+
request.action?.id === 'undo-runtime-values') {
|
|
2546
|
+
return this.apply(request);
|
|
2547
|
+
}
|
|
2548
|
+
const prompt = (request.prompt ?? '').trim();
|
|
2549
|
+
if (!prompt) {
|
|
2550
|
+
return Promise.resolve({
|
|
2551
|
+
state: 'listening',
|
|
2552
|
+
phase: 'capture',
|
|
2553
|
+
statusText: '',
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
const componentId = this.adapter.componentId || request.componentId || 'praxis-dynamic-form';
|
|
2557
|
+
const componentType = this.adapter.componentType || request.componentType || 'form';
|
|
2558
|
+
const currentState = this.toAiJsonObject(this.adapter.getCurrentConfig());
|
|
2559
|
+
const runtimeState = this.optionalJsonObject(this.adapter.getRuntimeState?.());
|
|
2560
|
+
const contextHints = this.mergeJsonObjects(this.optionalJsonObject(this.adapter.getAuthoringContext?.()), this.optionalJsonObject(request.action?.contextHints));
|
|
2561
|
+
if (this.shouldRestrictToInlineHelp(contextHints)) {
|
|
2562
|
+
return Promise.resolve(this.toInlineHelpOnlyResult(prompt, request, contextHints));
|
|
2563
|
+
}
|
|
2564
|
+
const buildRequest = async () => {
|
|
2565
|
+
await this.adapter.prepareAuthoringContext?.();
|
|
2566
|
+
const preparedRuntimeState = this.optionalJsonObject(this.adapter.getRuntimeState?.()) ?? runtimeState;
|
|
2567
|
+
const preparedContextHints = this.mergeJsonObjects(this.optionalJsonObject(this.adapter.getAuthoringContext?.()), this.optionalJsonObject(request.action?.contextHints));
|
|
2568
|
+
const dataProfile = this.optionalJsonObject(this.adapter.getDataProfile?.());
|
|
2569
|
+
const schemaFields = this.adapter.getSchemaFields?.()
|
|
2570
|
+
?.map((field) => this.toAiJsonObject(field))
|
|
2571
|
+
.filter((field) => Object.keys(field).length > 0);
|
|
2572
|
+
const patchRequest = withAuthoringScopePolicy({
|
|
2573
|
+
componentId,
|
|
2574
|
+
componentType,
|
|
2575
|
+
userPrompt: prompt,
|
|
2576
|
+
sessionId: request.sessionId,
|
|
2577
|
+
clientTurnId: request.clientTurnId,
|
|
2578
|
+
messages: this.toChatMessages(request.messages, prompt),
|
|
2579
|
+
currentState,
|
|
2580
|
+
currentStateDigest: this.buildCurrentStateDigest(currentState, preparedRuntimeState),
|
|
2581
|
+
uiContextRef: {
|
|
2582
|
+
componentId,
|
|
2583
|
+
componentType,
|
|
2584
|
+
},
|
|
2585
|
+
...(dataProfile ? { dataProfile } : {}),
|
|
2586
|
+
...(preparedRuntimeState ? { runtimeState: preparedRuntimeState } : {}),
|
|
2587
|
+
...(schemaFields?.length ? { schemaFields } : {}),
|
|
2588
|
+
...(preparedContextHints ? { contextHints: preparedContextHints } : {}),
|
|
2589
|
+
}, {
|
|
2590
|
+
componentId,
|
|
2591
|
+
componentType,
|
|
2592
|
+
componentLabel: this.adapter.componentName || 'formulário',
|
|
2593
|
+
});
|
|
2594
|
+
return {
|
|
2595
|
+
...patchRequest,
|
|
2596
|
+
targetApp: 'praxis-ui-angular',
|
|
2597
|
+
targetComponentId: componentId,
|
|
2598
|
+
currentPage: currentState,
|
|
2599
|
+
conversationMessages: this.toConversationMessages(request.messages),
|
|
2600
|
+
pendingClarification: this.toPendingClarification(request),
|
|
2601
|
+
attachmentSummaries: this.toAttachmentSummaries(request),
|
|
2602
|
+
activeSemanticDecision: this.optionalJsonObject(request.activeSemanticDecision ?? request.action?.activeSemanticDecision),
|
|
2603
|
+
contextHints: patchRequest.contextHints ?? null,
|
|
2604
|
+
};
|
|
2605
|
+
};
|
|
2606
|
+
return this.submitViaAgenticStream(request, buildRequest);
|
|
2607
|
+
}
|
|
2608
|
+
submitViaAgenticStream(request, buildRequest) {
|
|
2609
|
+
return new Observable((subscriber) => {
|
|
2610
|
+
let closed = false;
|
|
2611
|
+
let subscription = null;
|
|
2612
|
+
const close = () => {
|
|
2613
|
+
closed = true;
|
|
2614
|
+
subscription?.unsubscribe();
|
|
2615
|
+
subscription = null;
|
|
2616
|
+
};
|
|
2617
|
+
void buildRequest()
|
|
2618
|
+
.then((turnRequest) => {
|
|
2619
|
+
if (closed)
|
|
2620
|
+
return;
|
|
2621
|
+
subscription = this.turnClient.streamEvents(turnRequest, {
|
|
2622
|
+
initialStatusText: 'Preparando o contexto seguro do formulário.',
|
|
2623
|
+
resultTimeoutMs: 90_000,
|
|
2624
|
+
streamTimeoutMs: 90_000,
|
|
2625
|
+
}).subscribe({
|
|
2626
|
+
next: (event) => {
|
|
2627
|
+
if (closed)
|
|
2628
|
+
return;
|
|
2629
|
+
const result = this.toAgenticStreamTurnResult(event, request);
|
|
2630
|
+
subscriber.next(result);
|
|
2631
|
+
if (result.state !== 'processing') {
|
|
2632
|
+
subscriber.complete();
|
|
2633
|
+
close();
|
|
2634
|
+
}
|
|
2635
|
+
},
|
|
2636
|
+
error: (error) => {
|
|
2637
|
+
if (closed)
|
|
2638
|
+
return;
|
|
2639
|
+
subscriber.next(this.toAssistantErrorResult(error));
|
|
2640
|
+
subscriber.complete();
|
|
2641
|
+
close();
|
|
2642
|
+
},
|
|
2643
|
+
});
|
|
2644
|
+
})
|
|
2645
|
+
.catch((error) => {
|
|
2646
|
+
if (closed)
|
|
2647
|
+
return;
|
|
2648
|
+
subscriber.next(this.toAssistantErrorResult(error));
|
|
2649
|
+
subscriber.complete();
|
|
2650
|
+
close();
|
|
2651
|
+
});
|
|
2652
|
+
return () => close();
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
toAgenticStreamTurnResult(event, request) {
|
|
2656
|
+
if (event.kind === 'stream-started') {
|
|
2657
|
+
return {
|
|
2658
|
+
state: 'processing',
|
|
2659
|
+
phase: 'contextualize',
|
|
2660
|
+
statusText: 'Analisando o formulário e suas capacidades.',
|
|
2661
|
+
sessionId: event.start.threadId,
|
|
2662
|
+
clientTurnId: request.clientTurnId ?? event.start.turnId,
|
|
2663
|
+
observationId: event.start.observationId ?? null,
|
|
2664
|
+
canApply: false,
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
if (event.kind === 'stream-lifecycle') {
|
|
2668
|
+
return {
|
|
2669
|
+
state: 'processing',
|
|
2670
|
+
phase: 'contextualize',
|
|
2671
|
+
statusText: event.statusText,
|
|
2672
|
+
sessionId: event.start.threadId,
|
|
2673
|
+
clientTurnId: request.clientTurnId ?? event.start.turnId,
|
|
2674
|
+
observationId: event.start.observationId ?? null,
|
|
2675
|
+
canApply: false,
|
|
2676
|
+
diagnostics: event.diagnostics
|
|
2677
|
+
? { streamLifecycle: { phase: event.phase, ...event.diagnostics } }
|
|
2678
|
+
: undefined,
|
|
2679
|
+
};
|
|
2680
|
+
}
|
|
2681
|
+
if (event.event.type === 'result') {
|
|
2682
|
+
const payload = this.toRecord(event.event.payload) ?? {};
|
|
2683
|
+
const clientResult = this.turnClient.toTurnResult?.(event.event, request.clientTurnId);
|
|
2684
|
+
const contextHints = this.mergeJsonObjects(this.optionalJsonObject(this.adapter.getAuthoringContext?.()), this.optionalJsonObject(request.action?.contextHints));
|
|
2685
|
+
const localPatchAllowed = this.canApplyLocalPatch(contextHints);
|
|
2686
|
+
const payloadCanApply = payload['canApply'] !== false;
|
|
2687
|
+
const rawResponse = this.toRecord(payload['response']) ?? payload;
|
|
2688
|
+
const runtimeProposal = this.extractRuntimeValueProposal(payload['runtimeValueProposal']) ??
|
|
2689
|
+
this.extractRuntimeValueProposal(rawResponse['runtimeValueProposal']) ??
|
|
2690
|
+
this.extractRuntimeValueProposal(clientResult?.runtimeValueProposal) ??
|
|
2691
|
+
this.extractRuntimeValueProposal(clientResult?.pendingPatch);
|
|
2692
|
+
if (runtimeProposal) {
|
|
2693
|
+
return this.toRuntimeValueProposalTurnResult(runtimeProposal, payload, clientResult, request, event.event.threadId, event.event.turnId, contextHints);
|
|
2694
|
+
}
|
|
2695
|
+
const hasOrchestratorPayload = !!this.toRecord(payload['response']) ||
|
|
2696
|
+
typeof rawResponse['type'] === 'string' ||
|
|
2697
|
+
!!this.toRecord(rawResponse['patch']) ||
|
|
2698
|
+
!!this.toRecord(rawResponse['compiledPatch']) ||
|
|
2699
|
+
!!this.toRecord(rawResponse['componentEditPlan']);
|
|
2700
|
+
if (!hasOrchestratorPayload && clientResult) {
|
|
2701
|
+
const sanitizedMessage = !payloadCanApply
|
|
2702
|
+
? this.sanitizeBlockedAssistantMessage(clientResult.assistantMessage)
|
|
2703
|
+
: clientResult.assistantMessage;
|
|
2704
|
+
return {
|
|
2705
|
+
...clientResult,
|
|
2706
|
+
assistantMessage: sanitizedMessage,
|
|
2707
|
+
statusText: !payloadCanApply
|
|
2708
|
+
? clientResult.statusText || sanitizedMessage
|
|
2709
|
+
: clientResult.statusText,
|
|
2710
|
+
canApply: payloadCanApply && clientResult.canApply === true,
|
|
2711
|
+
pendingPatch: payloadCanApply ? clientResult.pendingPatch : null,
|
|
2712
|
+
sessionId: event.event.threadId || clientResult.sessionId || request.sessionId,
|
|
2713
|
+
clientTurnId: request.clientTurnId ?? clientResult.clientTurnId ?? event.event.turnId,
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
const response = this.normalizeAgenticResponse(rawResponse);
|
|
2717
|
+
const compiledResponse = this.compileAdapterResponse(response);
|
|
2718
|
+
if (compiledResponse.patch && Object.keys(compiledResponse.patch).length > 0 && !localPatchAllowed) {
|
|
2719
|
+
return {
|
|
2720
|
+
state: 'clarification',
|
|
2721
|
+
phase: 'clarify',
|
|
2722
|
+
sessionId: event.event.threadId || request.sessionId,
|
|
2723
|
+
clientTurnId: request.clientTurnId ?? event.event.turnId,
|
|
2724
|
+
observationId: compiledResponse.observationId ?? request.observationId ?? null,
|
|
2725
|
+
assistantMessage: 'Alterações estruturais de layout ou configuração exigem ativar "Editar layout" (enableCustomization = true). Sem esse modo ativo, posso orientar ou assistir o preenchimento operacional do formulário.',
|
|
2726
|
+
statusText: 'Modo de edição de layout desativado.',
|
|
2727
|
+
canApply: false,
|
|
2728
|
+
pendingPatch: null,
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2731
|
+
const turnResult = this.toTurnResult(compiledResponse, request);
|
|
2732
|
+
const mergedQuickReplies = turnResult.quickReplies?.length
|
|
2733
|
+
? turnResult.quickReplies
|
|
2734
|
+
: clientResult?.quickReplies;
|
|
2735
|
+
const mergedClarificationQuestions = turnResult.clarificationQuestions?.length
|
|
2736
|
+
? turnResult.clarificationQuestions
|
|
2737
|
+
: clientResult?.clarificationQuestions;
|
|
2738
|
+
if (!payloadCanApply) {
|
|
2739
|
+
const sanitizedMessage = this.sanitizeBlockedAssistantMessage(typeof payload['assistantMessage'] === 'string' && payload['assistantMessage'].trim()
|
|
2740
|
+
? payload['assistantMessage'].trim()
|
|
2741
|
+
: turnResult.assistantMessage);
|
|
2742
|
+
const requiresUserDecision = turnResult.state === 'clarification' ||
|
|
2743
|
+
turnResult.state === 'review' ||
|
|
2744
|
+
(mergedQuickReplies?.length ?? 0) > 0 ||
|
|
2745
|
+
(mergedClarificationQuestions?.length ?? 0) > 0;
|
|
2746
|
+
const blockedState = turnResult.state === 'error'
|
|
2747
|
+
? 'error'
|
|
2748
|
+
: requiresUserDecision
|
|
2749
|
+
? 'clarification'
|
|
2750
|
+
: 'success';
|
|
2751
|
+
const blockedPhase = turnResult.state === 'error'
|
|
2752
|
+
? 'capture'
|
|
2753
|
+
: requiresUserDecision
|
|
2754
|
+
? 'clarify'
|
|
2755
|
+
: 'summarize';
|
|
2756
|
+
return {
|
|
2757
|
+
...turnResult,
|
|
2758
|
+
...(mergedQuickReplies ? { quickReplies: mergedQuickReplies } : {}),
|
|
2759
|
+
...(mergedClarificationQuestions ? { clarificationQuestions: mergedClarificationQuestions } : {}),
|
|
2760
|
+
...(clientResult?.assistantContent && !turnResult.assistantContent
|
|
2761
|
+
? { assistantContent: clientResult.assistantContent }
|
|
2762
|
+
: {}),
|
|
2763
|
+
...(clientResult?.diagnostics && !turnResult.diagnostics
|
|
2764
|
+
? { diagnostics: clientResult.diagnostics }
|
|
2765
|
+
: {}),
|
|
2766
|
+
state: blockedState,
|
|
2767
|
+
phase: blockedPhase,
|
|
2768
|
+
assistantMessage: sanitizedMessage,
|
|
2769
|
+
statusText: typeof payload['statusText'] === 'string' && payload['statusText'].trim()
|
|
2770
|
+
? payload['statusText'].trim()
|
|
2771
|
+
: requiresUserDecision
|
|
2772
|
+
? 'Revisão necessária antes de aplicar.'
|
|
2773
|
+
: sanitizedMessage,
|
|
2774
|
+
canApply: false,
|
|
2775
|
+
pendingPatch: null,
|
|
2776
|
+
sessionId: event.event.threadId || request.sessionId,
|
|
2777
|
+
clientTurnId: request.clientTurnId ?? event.event.turnId,
|
|
2778
|
+
};
|
|
2779
|
+
}
|
|
2780
|
+
return {
|
|
2781
|
+
...turnResult,
|
|
2782
|
+
...(mergedQuickReplies ? { quickReplies: mergedQuickReplies } : {}),
|
|
2783
|
+
...(mergedClarificationQuestions ? { clarificationQuestions: mergedClarificationQuestions } : {}),
|
|
2784
|
+
...(clientResult?.assistantContent && !turnResult.assistantContent
|
|
2785
|
+
? { assistantContent: clientResult.assistantContent }
|
|
2786
|
+
: {}),
|
|
2787
|
+
...(clientResult?.diagnostics && !turnResult.diagnostics
|
|
2788
|
+
? { diagnostics: clientResult.diagnostics }
|
|
2789
|
+
: {}),
|
|
2790
|
+
sessionId: event.event.threadId || request.sessionId,
|
|
2791
|
+
clientTurnId: request.clientTurnId ?? event.event.turnId,
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
return this.turnClient.toTurnResult(event.event, request.clientTurnId);
|
|
2795
|
+
}
|
|
2796
|
+
normalizeAgenticResponse(response) {
|
|
2797
|
+
const type = response['type'];
|
|
2798
|
+
const normalizedType = type === 'patch'
|
|
2799
|
+
|| type === 'clarification'
|
|
2800
|
+
|| type === 'error'
|
|
2801
|
+
|| type === 'info'
|
|
2802
|
+
? type
|
|
2803
|
+
: this.toRecord(response['patch']) || this.toRecord(response['compiledPatch'])
|
|
2804
|
+
? 'patch'
|
|
2805
|
+
: 'info';
|
|
2806
|
+
const patch = this.toRecord(response['patch']) ?? this.toRecord(response['compiledPatch']) ?? undefined;
|
|
2807
|
+
const message = typeof response['message'] === 'string'
|
|
2808
|
+
? response['message']
|
|
2809
|
+
: typeof response['assistantMessage'] === 'string'
|
|
2810
|
+
? response['assistantMessage']
|
|
2811
|
+
: undefined;
|
|
2812
|
+
return {
|
|
2813
|
+
...response,
|
|
2814
|
+
type: normalizedType,
|
|
2815
|
+
...(patch ? { patch } : {}),
|
|
2816
|
+
...(message ? { message } : {}),
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
toConversationMessages(messages) {
|
|
2820
|
+
return (messages ?? [])
|
|
2821
|
+
.filter((message) => message.role === 'user' || message.role === 'assistant' || message.role === 'system')
|
|
2822
|
+
.map((message) => ({
|
|
2823
|
+
id: message.id,
|
|
2824
|
+
role: message.role,
|
|
2825
|
+
text: message.text,
|
|
2826
|
+
}))
|
|
2827
|
+
.filter((message) => message.text.trim().length > 0);
|
|
2828
|
+
}
|
|
2829
|
+
toPendingClarification(request) {
|
|
2830
|
+
const pending = request.pendingClarification;
|
|
2831
|
+
if (!pending?.sourcePrompt?.trim())
|
|
2832
|
+
return null;
|
|
2833
|
+
return {
|
|
2834
|
+
sourcePrompt: pending.sourcePrompt,
|
|
2835
|
+
questions: pending.questions.map((question) => question.label).filter(Boolean),
|
|
2836
|
+
assistantMessage: pending.assistantMessage ?? null,
|
|
2837
|
+
clientTurnId: pending.clientTurnId ?? null,
|
|
2838
|
+
diagnostics: this.optionalJsonObject(pending.diagnostics) ?? null,
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
toAttachmentSummaries(request) {
|
|
2842
|
+
return (request.attachments ?? []).map((attachment) => ({
|
|
2843
|
+
id: attachment.id,
|
|
2844
|
+
name: attachment.name,
|
|
2845
|
+
kind: attachment.kind,
|
|
2846
|
+
mimeType: attachment.mimeType ?? null,
|
|
2847
|
+
sizeBytes: attachment.sizeBytes ?? null,
|
|
2848
|
+
source: attachment.source ?? null,
|
|
2849
|
+
hasPreview: !!attachment.previewUrl,
|
|
2850
|
+
}));
|
|
2851
|
+
}
|
|
2852
|
+
toAssistantErrorResult(error) {
|
|
2853
|
+
const message = error instanceof Error
|
|
2854
|
+
? error.message
|
|
2855
|
+
: typeof error === 'string' && error.trim()
|
|
2856
|
+
? error
|
|
2857
|
+
: 'Não foi possível concluir o pedido do formulário.';
|
|
2858
|
+
return {
|
|
2859
|
+
state: 'error',
|
|
2860
|
+
phase: 'capture',
|
|
2861
|
+
assistantMessage: `Não consegui concluir este pedido. ${message}`,
|
|
2862
|
+
errorText: message,
|
|
2863
|
+
canApply: false,
|
|
2864
|
+
pendingPatch: null,
|
|
2865
|
+
};
|
|
2866
|
+
}
|
|
2867
|
+
async apply(request) {
|
|
2868
|
+
const contextHints = this.mergeJsonObjects(this.optionalJsonObject(this.adapter.getAuthoringContext?.()), this.optionalJsonObject(request.action?.contextHints));
|
|
2869
|
+
if (this.shouldRestrictToInlineHelp(contextHints)) {
|
|
2870
|
+
return {
|
|
2871
|
+
state: 'error',
|
|
2872
|
+
phase: 'apply',
|
|
2873
|
+
assistantMessage: 'Este formulario esta em modo de leitura. Posso explicar ou diagnosticar, mas nao aplicar mudancas locais.',
|
|
2874
|
+
errorText: 'Aplicacao bloqueada em view/readonly sem customizacao.',
|
|
2875
|
+
canApply: false,
|
|
2876
|
+
pendingPatch: null,
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2879
|
+
if (request.action?.kind === 'runtime-form-value-undo' ||
|
|
2880
|
+
request.action?.id === 'undo-runtime-values') {
|
|
2881
|
+
return this.applyRuntimeValueUndo(request);
|
|
2882
|
+
}
|
|
2883
|
+
const runtimeProposal = this.extractRuntimeValueProposal(request.runtimeValueProposal) ??
|
|
2884
|
+
this.extractRuntimeValueProposal(request.pendingPatch);
|
|
2885
|
+
if (runtimeProposal) {
|
|
2886
|
+
return this.applyRuntimeValueProposal(runtimeProposal, request, contextHints);
|
|
2887
|
+
}
|
|
2888
|
+
if (!this.canApplyLocalPatch(contextHints)) {
|
|
2889
|
+
return {
|
|
2890
|
+
state: 'error',
|
|
2891
|
+
phase: 'apply',
|
|
2892
|
+
assistantMessage: 'Alterações estruturais de layout ou configuração exigem ativar "Editar layout" (enableCustomization = true).',
|
|
2893
|
+
errorText: 'Aplicação de patch estrutural bloqueada com enableCustomization = false.',
|
|
2894
|
+
canApply: false,
|
|
2895
|
+
pendingPatch: null,
|
|
2896
|
+
};
|
|
2897
|
+
}
|
|
2898
|
+
const patch = this.toRecord(request.pendingPatch);
|
|
2899
|
+
if (!patch) {
|
|
2900
|
+
return {
|
|
2901
|
+
state: 'error',
|
|
2902
|
+
phase: 'apply',
|
|
2903
|
+
assistantMessage: 'Nao ha alteracao de formulario pronta para aplicar.',
|
|
2904
|
+
errorText: 'Nao ha alteracao de formulario pronta para aplicar.',
|
|
2905
|
+
canApply: false,
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2908
|
+
const result = await this.adapter.applyPatch(patch, request.prompt);
|
|
2909
|
+
if (!result.success) {
|
|
2910
|
+
return {
|
|
2911
|
+
state: 'error',
|
|
2912
|
+
phase: 'apply',
|
|
2913
|
+
assistantMessage: result.error || 'Nao foi possivel aplicar as alteracoes no formulario.',
|
|
2914
|
+
errorText: result.error || 'Nao foi possivel aplicar as alteracoes no formulario.',
|
|
2915
|
+
canApply: true,
|
|
2916
|
+
pendingPatch: patch,
|
|
2917
|
+
};
|
|
2918
|
+
}
|
|
2919
|
+
return {
|
|
2920
|
+
state: 'success',
|
|
2921
|
+
phase: 'summarize',
|
|
2922
|
+
assistantMessage: 'Alteracoes aplicadas no formulario.',
|
|
2923
|
+
statusText: 'Alteracoes aplicadas no formulario.',
|
|
2924
|
+
canApply: false,
|
|
2925
|
+
pendingPatch: null,
|
|
2926
|
+
diagnostics: result.warnings?.length ? { warnings: result.warnings } : undefined,
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2929
|
+
cancel() {
|
|
2930
|
+
return Promise.resolve({
|
|
2931
|
+
state: 'listening',
|
|
2932
|
+
phase: 'capture',
|
|
2933
|
+
assistantMessage: 'Solicitacao cancelada.',
|
|
2934
|
+
statusText: '',
|
|
2935
|
+
canApply: false,
|
|
2936
|
+
pendingPatch: null,
|
|
2937
|
+
pendingClarification: null,
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2940
|
+
retry(request) {
|
|
2941
|
+
const lastPrompt = [...(request.messages ?? [])].reverse()
|
|
2942
|
+
.find((message) => message.role === 'user')?.text;
|
|
2943
|
+
return this.submit({
|
|
2944
|
+
...request,
|
|
2945
|
+
prompt: lastPrompt ?? request.prompt,
|
|
2946
|
+
action: { kind: 'retry' },
|
|
2947
|
+
});
|
|
2948
|
+
}
|
|
2949
|
+
toTurnResult(response, request) {
|
|
2950
|
+
if (!response) {
|
|
2951
|
+
return {
|
|
2952
|
+
state: 'error',
|
|
2953
|
+
phase: 'capture',
|
|
2954
|
+
assistantMessage: 'Resposta vazia da IA.',
|
|
2955
|
+
errorText: 'Resposta vazia da IA.',
|
|
2956
|
+
};
|
|
2957
|
+
}
|
|
2958
|
+
if (response.type === 'clarification') {
|
|
2959
|
+
const questions = this.toClarificationQuestions(response);
|
|
2960
|
+
const assistantMessage = this.sanitizeBlockedAssistantMessage(response.message || 'Preciso de mais detalhes para continuar.');
|
|
2961
|
+
return {
|
|
2962
|
+
state: 'clarification',
|
|
2963
|
+
phase: 'clarify',
|
|
2964
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
2965
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
2966
|
+
assistantMessage,
|
|
2967
|
+
clarificationQuestions: questions,
|
|
2968
|
+
quickReplies: this.toQuickReplies(response),
|
|
2969
|
+
canApply: false,
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
if (response.type === 'info') {
|
|
2973
|
+
const message = this.sanitizeBlockedAssistantMessage(response.message || response.explanation || 'Informacao gerada.');
|
|
2974
|
+
return {
|
|
2975
|
+
state: 'success',
|
|
2976
|
+
phase: 'summarize',
|
|
2977
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
2978
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
2979
|
+
assistantMessage: message,
|
|
2980
|
+
statusText: message,
|
|
2981
|
+
canApply: false,
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
if (response.type === 'error') {
|
|
2985
|
+
const message = response.message || 'Falha ao gerar alteracao de formulario.';
|
|
2986
|
+
return {
|
|
2987
|
+
state: 'error',
|
|
2988
|
+
phase: 'capture',
|
|
2989
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
2990
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
2991
|
+
assistantMessage: message,
|
|
2992
|
+
errorText: message,
|
|
2993
|
+
diagnostics: response.warnings?.length ? { warnings: response.warnings } : undefined,
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
if (response.patch && Object.keys(response.patch).length > 0) {
|
|
2997
|
+
const warnings = response.warnings?.filter(Boolean) ?? [];
|
|
2998
|
+
const suffix = warnings.length ? ` Avisos: ${warnings.join('; ')}` : '';
|
|
2999
|
+
return {
|
|
3000
|
+
state: 'review',
|
|
3001
|
+
phase: 'review',
|
|
3002
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
3003
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
3004
|
+
assistantMessage: `${response.explanation || 'Proposta de alteracao pronta para revisar.'}${suffix}`,
|
|
3005
|
+
statusText: 'Revise a proposta antes de aplicar.',
|
|
3006
|
+
canApply: true,
|
|
3007
|
+
pendingPatch: response.patch,
|
|
3008
|
+
preview: {
|
|
3009
|
+
kind: 'dynamic-form-config-patch',
|
|
3010
|
+
diff: response.diff ?? [],
|
|
3011
|
+
},
|
|
3012
|
+
diagnostics: warnings.length ? { warnings } : undefined,
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
return {
|
|
3016
|
+
state: 'success',
|
|
3017
|
+
phase: 'summarize',
|
|
3018
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
3019
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
3020
|
+
assistantMessage: response.message || response.explanation || 'Nenhuma alteracao necessaria.',
|
|
3021
|
+
statusText: response.message || response.explanation || 'Nenhuma alteracao necessaria.',
|
|
3022
|
+
canApply: false,
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
compileAdapterResponse(response) {
|
|
3026
|
+
const compiled = this.adapter.compileAiResponse?.(response);
|
|
3027
|
+
if (!compiled && response.patch && Object.keys(response.patch).length > 0) {
|
|
3028
|
+
return {
|
|
3029
|
+
type: 'error',
|
|
3030
|
+
message: 'O formulario exige componentEditPlan validado pelo manifesto antes de gerar patch local.',
|
|
3031
|
+
warnings: [
|
|
3032
|
+
'free-dynamic-form-patch-rejected',
|
|
3033
|
+
'Use componentEditPlan validado contra PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST.',
|
|
3034
|
+
],
|
|
3035
|
+
};
|
|
3036
|
+
}
|
|
3037
|
+
if (!compiled) {
|
|
3038
|
+
return response;
|
|
3039
|
+
}
|
|
3040
|
+
if (compiled.type === 'error') {
|
|
3041
|
+
return {
|
|
3042
|
+
type: 'error',
|
|
3043
|
+
message: compiled.message || 'O componentEditPlan do formulario nao passou na validacao de capacidades.',
|
|
3044
|
+
warnings: compiled.warnings,
|
|
3045
|
+
};
|
|
3046
|
+
}
|
|
3047
|
+
const warnings = [
|
|
3048
|
+
...(response.warnings ?? []),
|
|
3049
|
+
...(compiled.warnings ?? []),
|
|
3050
|
+
];
|
|
3051
|
+
return {
|
|
3052
|
+
...response,
|
|
3053
|
+
...compiled,
|
|
3054
|
+
patch: compiled.patch,
|
|
3055
|
+
warnings: warnings.length ? warnings : undefined,
|
|
3056
|
+
};
|
|
3057
|
+
}
|
|
3058
|
+
toChatMessages(messages, prompt) {
|
|
3059
|
+
const supported = (messages ?? [])
|
|
3060
|
+
.filter((message) => message.role === 'user' || message.role === 'assistant' || message.role === 'system')
|
|
3061
|
+
.map((message) => ({
|
|
3062
|
+
role: message.role,
|
|
3063
|
+
content: message.text,
|
|
3064
|
+
}))
|
|
3065
|
+
.filter((message) => message.content.trim().length > 0);
|
|
3066
|
+
return supported.length ? supported : [{ role: 'user', content: prompt }];
|
|
3067
|
+
}
|
|
3068
|
+
toClarificationQuestions(response) {
|
|
3069
|
+
const labels = response.questions?.length
|
|
3070
|
+
? response.questions
|
|
3071
|
+
: response.message
|
|
3072
|
+
? [response.message]
|
|
3073
|
+
: ['Qual ajuste voce quer aplicar no formulario?'];
|
|
3074
|
+
const options = this.toQuickReplies(response).map((reply) => ({
|
|
3075
|
+
id: reply.id,
|
|
3076
|
+
label: reply.label,
|
|
3077
|
+
value: reply.prompt,
|
|
3078
|
+
description: reply.description ?? undefined,
|
|
3079
|
+
contextHints: reply.contextHints ? { ...reply.contextHints } : undefined,
|
|
3080
|
+
}));
|
|
3081
|
+
return labels.map((label, index) => ({
|
|
3082
|
+
id: `dynamic-form-clarification-${index + 1}`,
|
|
3083
|
+
type: options.length ? 'single-choice' : 'text',
|
|
3084
|
+
label,
|
|
3085
|
+
allowCustom: true,
|
|
3086
|
+
options,
|
|
3087
|
+
}));
|
|
3088
|
+
}
|
|
3089
|
+
toQuickReplies(response) {
|
|
3090
|
+
const payloads = response.optionPayloads ?? [];
|
|
3091
|
+
if (payloads.length) {
|
|
3092
|
+
return payloads
|
|
3093
|
+
.map((option, index) => {
|
|
3094
|
+
const label = option.label?.trim() || option.value?.trim() || `Opcao ${index + 1}`;
|
|
3095
|
+
const prompt = option.value?.trim() || option.example?.trim() || label;
|
|
3096
|
+
return {
|
|
3097
|
+
id: `option-${index + 1}`,
|
|
3098
|
+
label,
|
|
3099
|
+
prompt,
|
|
3100
|
+
kind: 'clarification-option',
|
|
3101
|
+
description: option.example?.trim() || undefined,
|
|
3102
|
+
contextHints: this.optionalJsonObject(option.contextHints),
|
|
3103
|
+
};
|
|
3104
|
+
});
|
|
3105
|
+
}
|
|
3106
|
+
return (response.options ?? [])
|
|
3107
|
+
.filter((option) => !!option?.trim())
|
|
3108
|
+
.map((option, index) => ({
|
|
3109
|
+
id: `option-${index + 1}`,
|
|
3110
|
+
label: option.trim(),
|
|
3111
|
+
prompt: option.trim(),
|
|
3112
|
+
kind: 'clarification-option',
|
|
3113
|
+
description: undefined,
|
|
3114
|
+
contextHints: undefined,
|
|
3115
|
+
}));
|
|
3116
|
+
}
|
|
3117
|
+
buildCurrentStateDigest(currentState, runtimeState) {
|
|
3118
|
+
const fields = Array.isArray(currentState['fieldMetadata'])
|
|
3119
|
+
? currentState['fieldMetadata']
|
|
3120
|
+
.map((field) => this.toRecord(field)?.['name'])
|
|
3121
|
+
.filter((field) => typeof field === 'string' && field.length > 0)
|
|
3122
|
+
: undefined;
|
|
3123
|
+
const sections = Array.isArray(currentState['sections']) ? currentState['sections'].length : undefined;
|
|
3124
|
+
return {
|
|
3125
|
+
...(fields?.length ? { columns: fields } : {}),
|
|
3126
|
+
...(typeof runtimeState?.['totalFields'] === 'number'
|
|
3127
|
+
? { rowCount: runtimeState['totalFields'] }
|
|
3128
|
+
: sections !== undefined
|
|
3129
|
+
? { rowCount: sections }
|
|
3130
|
+
: {}),
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3133
|
+
shouldRestrictToInlineHelp(contextHints) {
|
|
3134
|
+
const policy = this.toRecord(contextHints?.['runtimeAuthoringPolicy']);
|
|
3135
|
+
return policy?.['canApplyLocalPatch'] === false && policy?.['canAssistRuntimeValues'] !== true;
|
|
3136
|
+
}
|
|
3137
|
+
canApplyLocalPatch(contextHints) {
|
|
3138
|
+
const policy = this.toRecord(contextHints?.['runtimeAuthoringPolicy']);
|
|
3139
|
+
return policy?.['canApplyLocalPatch'] !== false;
|
|
3140
|
+
}
|
|
3141
|
+
canAssistRuntimeValues(contextHints) {
|
|
3142
|
+
const policy = this.toRecord(contextHints?.['runtimeAuthoringPolicy']);
|
|
3143
|
+
return policy?.['canAssistRuntimeValues'] === true;
|
|
3144
|
+
}
|
|
3145
|
+
extractRuntimeValueProposal(candidate) {
|
|
3146
|
+
const record = this.toRecord(candidate);
|
|
3147
|
+
if (!record ||
|
|
3148
|
+
record['schemaVersion'] !== PRAXIS_RUNTIME_FORM_VALUE_PROPOSAL_SCHEMA_VERSION) {
|
|
3149
|
+
return null;
|
|
3150
|
+
}
|
|
3151
|
+
return record;
|
|
3152
|
+
}
|
|
3153
|
+
toRuntimeValueProposalTurnResult(proposal, payload, clientResult, request, threadId, turnId, contextHints) {
|
|
3154
|
+
const runtimeAdapter = this.adapter;
|
|
3155
|
+
const localPreview = runtimeAdapter.previewRuntimeValues?.(proposal) ?? null;
|
|
3156
|
+
const payloadCanApply = payload['canApply'] !== false && this.canAssistRuntimeValues(contextHints);
|
|
3157
|
+
const effectiveCanApply = payloadCanApply && (localPreview ? localPreview.canApply : (proposal.assignments?.length ?? 0) > 0);
|
|
3158
|
+
const rawAssistantMessage = (typeof payload['assistantMessage'] === 'string' && payload['assistantMessage'].trim()
|
|
3159
|
+
? payload['assistantMessage'].trim()
|
|
3160
|
+
: clientResult?.assistantMessage) ||
|
|
3161
|
+
(effectiveCanApply
|
|
3162
|
+
? 'Proposta de preenchimento pronta para revisão por campo.'
|
|
3163
|
+
: localPreview?.blockMessage || 'A proposta de preenchimento não pôde ser aplicada automaticamente.');
|
|
3164
|
+
const assistantMessage = effectiveCanApply
|
|
3165
|
+
? rawAssistantMessage
|
|
3166
|
+
: this.sanitizeBlockedAssistantMessage(rawAssistantMessage);
|
|
3167
|
+
return {
|
|
3168
|
+
...(clientResult ?? { state: effectiveCanApply ? 'review' : 'clarification' }),
|
|
3169
|
+
state: effectiveCanApply ? 'review' : 'clarification',
|
|
3170
|
+
phase: effectiveCanApply ? 'review' : 'clarify',
|
|
3171
|
+
sessionId: threadId || clientResult?.sessionId || request.sessionId,
|
|
3172
|
+
clientTurnId: request.clientTurnId ?? clientResult?.clientTurnId ?? turnId,
|
|
3173
|
+
assistantMessage,
|
|
3174
|
+
statusText: effectiveCanApply
|
|
3175
|
+
? 'Revise os campos propostos antes de aplicar.'
|
|
3176
|
+
: localPreview?.blockMessage || 'Revisão necessária antes de aplicar.',
|
|
3177
|
+
canApply: effectiveCanApply,
|
|
3178
|
+
pendingPatch: effectiveCanApply ? proposal : null,
|
|
3179
|
+
runtimeValueProposal: proposal,
|
|
3180
|
+
preview: {
|
|
3181
|
+
kind: 'runtime-form-value-proposal',
|
|
3182
|
+
proposal,
|
|
3183
|
+
...(localPreview ? { runtimePreview: localPreview } : {}),
|
|
3184
|
+
},
|
|
3185
|
+
};
|
|
3186
|
+
}
|
|
3187
|
+
async applyRuntimeValueProposal(proposal, request, contextHints) {
|
|
3188
|
+
if (!this.canAssistRuntimeValues(contextHints)) {
|
|
3189
|
+
return {
|
|
3190
|
+
state: 'error',
|
|
3191
|
+
phase: 'apply',
|
|
3192
|
+
assistantMessage: 'Este formulário não aceita aplicação transitória de valores no modo atual.',
|
|
3193
|
+
errorText: 'Assistência de preenchimento indisponível neste modo.',
|
|
3194
|
+
canApply: false,
|
|
3195
|
+
pendingPatch: null,
|
|
3196
|
+
};
|
|
3197
|
+
}
|
|
3198
|
+
const runtimeAdapter = this.adapter;
|
|
3199
|
+
if (!runtimeAdapter.applyRuntimeValues) {
|
|
3200
|
+
return {
|
|
3201
|
+
state: 'error',
|
|
3202
|
+
phase: 'apply',
|
|
3203
|
+
assistantMessage: 'O adaptador atual do formulário não suporta aplicação transitória de valores.',
|
|
3204
|
+
errorText: 'Adaptador sem suporte a applyRuntimeValues.',
|
|
3205
|
+
canApply: false,
|
|
3206
|
+
pendingPatch: null,
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
const actionHints = this.toRecord(request.action?.contextHints);
|
|
3210
|
+
const selectedFieldPaths = Array.isArray(actionHints?.['selectedFieldPaths'])
|
|
3211
|
+
? actionHints['selectedFieldPaths'].filter((item) => typeof item === 'string' && item.trim().length > 0)
|
|
3212
|
+
: undefined;
|
|
3213
|
+
const applyModeCandidate = actionHints?.['applyMode'];
|
|
3214
|
+
const applyMode = applyModeCandidate === 'empty-only' || applyModeCandidate === 'selected-fields'
|
|
3215
|
+
? applyModeCandidate
|
|
3216
|
+
: undefined;
|
|
3217
|
+
const receipt = await runtimeAdapter.applyRuntimeValues({
|
|
3218
|
+
proposal,
|
|
3219
|
+
selectedFieldPaths,
|
|
3220
|
+
applyMode,
|
|
3221
|
+
});
|
|
3222
|
+
if (!receipt || receipt.appliedFields.length === 0) {
|
|
3223
|
+
const warningText = receipt?.warnings?.[receipt.warnings.length - 1] ||
|
|
3224
|
+
'Nenhum campo pôde ser aplicado no estado atual do formulário.';
|
|
3225
|
+
return {
|
|
3226
|
+
state: 'error',
|
|
3227
|
+
phase: 'apply',
|
|
3228
|
+
assistantMessage: warningText,
|
|
3229
|
+
errorText: warningText,
|
|
3230
|
+
canApply: false,
|
|
3231
|
+
pendingPatch: null,
|
|
3232
|
+
runtimeValueProposal: proposal,
|
|
3233
|
+
diagnostics: receipt
|
|
3234
|
+
? { runtimeValueApplyReceipt: receipt }
|
|
3235
|
+
: undefined,
|
|
3236
|
+
};
|
|
3237
|
+
}
|
|
3238
|
+
const appliedCount = receipt.appliedFields.length;
|
|
3239
|
+
const preservedCount = receipt.preservedFields.length;
|
|
3240
|
+
const rejectedCount = receipt.rejectedFields.length;
|
|
3241
|
+
const summaryParts = [`${appliedCount} campo(s) preenchido(s) no rascunho`];
|
|
3242
|
+
if (preservedCount > 0) {
|
|
3243
|
+
summaryParts.push(`${preservedCount} preservado(s)`);
|
|
3244
|
+
}
|
|
3245
|
+
if (rejectedCount > 0) {
|
|
3246
|
+
summaryParts.push(`${rejectedCount} rejeitado(s)`);
|
|
3247
|
+
}
|
|
3248
|
+
const summaryText = `${summaryParts.join(', ')}. Revise e clique em Salvar no formulário quando desejar persistir.`;
|
|
3249
|
+
return {
|
|
3250
|
+
state: 'success',
|
|
3251
|
+
phase: 'summarize',
|
|
3252
|
+
assistantMessage: summaryText,
|
|
3253
|
+
statusText: summaryText,
|
|
3254
|
+
canApply: false,
|
|
3255
|
+
pendingPatch: null,
|
|
3256
|
+
runtimeValueProposal: proposal,
|
|
3257
|
+
runtimeValueReceipt: receipt,
|
|
3258
|
+
preview: {
|
|
3259
|
+
kind: 'runtime-form-value-receipt',
|
|
3260
|
+
receipt,
|
|
3261
|
+
},
|
|
3262
|
+
quickReplies: receipt.canUndo
|
|
3263
|
+
? [
|
|
3264
|
+
{
|
|
3265
|
+
id: 'undo-runtime-values',
|
|
3266
|
+
label: 'Desfazer preenchimento',
|
|
3267
|
+
prompt: 'Desfazer preenchimento aplicado',
|
|
3268
|
+
kind: 'runtime-form-value-undo',
|
|
3269
|
+
icon: 'undo',
|
|
3270
|
+
contextHints: {
|
|
3271
|
+
receiptId: receipt.receiptId,
|
|
3272
|
+
},
|
|
3273
|
+
},
|
|
3274
|
+
]
|
|
3275
|
+
: [],
|
|
3276
|
+
diagnostics: {
|
|
3277
|
+
runtimeValueApplyReceipt: receipt,
|
|
3278
|
+
},
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
async applyRuntimeValueUndo(request) {
|
|
3282
|
+
const runtimeAdapter = this.adapter;
|
|
3283
|
+
const actionHints = this.toRecord(request.action?.contextHints);
|
|
3284
|
+
const receiptId = typeof actionHints?.['receiptId'] === 'string'
|
|
3285
|
+
? actionHints['receiptId']
|
|
3286
|
+
: typeof request.action?.value === 'string'
|
|
3287
|
+
? request.action.value
|
|
3288
|
+
: undefined;
|
|
3289
|
+
const undoReceipt = await runtimeAdapter.undoRuntimeValues?.(receiptId);
|
|
3290
|
+
if (!undoReceipt || undoReceipt.revertedFields.length === 0) {
|
|
3291
|
+
const preservedMsg = undoReceipt && undoReceipt.preservedManualFields.length > 0
|
|
3292
|
+
? `Nenhum campo foi revertido porque ${undoReceipt.preservedManualFields.length} campo(s) foram editados manualmente após a aplicação.`
|
|
3293
|
+
: 'Não há preenchimento pendente para desfazer nesta instância.';
|
|
3294
|
+
return {
|
|
3295
|
+
state: 'success',
|
|
3296
|
+
phase: 'summarize',
|
|
3297
|
+
assistantMessage: preservedMsg,
|
|
3298
|
+
statusText: preservedMsg,
|
|
3299
|
+
canApply: false,
|
|
3300
|
+
pendingPatch: null,
|
|
3301
|
+
diagnostics: undoReceipt
|
|
3302
|
+
? { runtimeValueUndoReceipt: undoReceipt }
|
|
3303
|
+
: undefined,
|
|
3304
|
+
};
|
|
3305
|
+
}
|
|
3306
|
+
const manualSuffix = undoReceipt.preservedManualFields.length > 0
|
|
3307
|
+
? ` (${undoReceipt.preservedManualFields.length} campo(s) editado(s) manualmente foram preservados).`
|
|
3308
|
+
: '.';
|
|
3309
|
+
const message = `Preenchimento desfeito em ${undoReceipt.revertedFields.length} campo(s)${manualSuffix}`;
|
|
3310
|
+
return {
|
|
3311
|
+
state: 'success',
|
|
3312
|
+
phase: 'summarize',
|
|
3313
|
+
assistantMessage: message,
|
|
3314
|
+
statusText: message,
|
|
3315
|
+
canApply: false,
|
|
3316
|
+
pendingPatch: null,
|
|
3317
|
+
preview: {
|
|
3318
|
+
kind: 'runtime-form-value-undo-receipt',
|
|
3319
|
+
undoReceipt,
|
|
3320
|
+
},
|
|
3321
|
+
diagnostics: {
|
|
3322
|
+
runtimeValueUndoReceipt: undoReceipt,
|
|
3323
|
+
},
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3326
|
+
sanitizeBlockedAssistantMessage(message) {
|
|
3327
|
+
const trimmed = (message ?? '').trim();
|
|
3328
|
+
if (!trimmed) {
|
|
3329
|
+
return 'Esta operação não pôde ser executada automaticamente neste turno. Revise o escopo ou informe os dados desejados.';
|
|
3330
|
+
}
|
|
3331
|
+
const kept = trimmed
|
|
3332
|
+
.split(/(?<=[.!?])\s+/)
|
|
3333
|
+
.map((part) => part.trim())
|
|
3334
|
+
.filter((part) => part.length > 0 && !this.isFalseExecutionPromiseSentence(part));
|
|
3335
|
+
if (kept.length === 0) {
|
|
3336
|
+
return 'Esta operação não pôde ser executada automaticamente neste turno. Revise o escopo ou informe os dados desejados.';
|
|
3337
|
+
}
|
|
3338
|
+
return kept.join(' ');
|
|
3339
|
+
}
|
|
3340
|
+
isFalseExecutionPromiseSentence(sentence) {
|
|
3341
|
+
return (/^(pronto|feito|conclu[ií]do|done|ready)[.!]*$/i.test(sentence) ||
|
|
3342
|
+
/\b(preenchi|preenchemos|preenchido[s]?|apliquei|aplicamos|salvei|salvamos)\b.*\b(campo[s]?|formul[aá]rio|altera[cç][oõ]es|configura[cç][aã]o|valores)\b/i.test(sentence) ||
|
|
3343
|
+
/\b(confirme|clique)\s+para\s+(aplicar|salvar|preencher|materializar)\b/i.test(sentence) ||
|
|
3344
|
+
/\bdeseja\s+(aplicar|salvar|materializar)\s+(a\s+configura[cç][aã]o|o\s+patch|as\s+altera[cç][oõ]es|os\s+valores)\b/i.test(sentence) ||
|
|
3345
|
+
/\bposso\s+aplicar\s+agora\b/i.test(sentence));
|
|
3346
|
+
}
|
|
3347
|
+
toInlineHelpOnlyResult(prompt, request, contextHints) {
|
|
3348
|
+
const policy = this.toRecord(contextHints?.['runtimeAuthoringPolicy']);
|
|
3349
|
+
const reason = typeof policy?.['reason'] === 'string'
|
|
3350
|
+
? policy['reason']
|
|
3351
|
+
: 'Formulario em modo de leitura ou readonly.';
|
|
3352
|
+
return {
|
|
3353
|
+
state: 'success',
|
|
3354
|
+
phase: 'summarize',
|
|
3355
|
+
sessionId: request.sessionId,
|
|
3356
|
+
assistantMessage: `Posso ajudar explicando este formulario ou diagnosticando o estado atual, mas nao vou aplicar alteracoes locais aqui. Motivo: ${reason}`,
|
|
3357
|
+
statusText: 'Modo somente assistencia.',
|
|
3358
|
+
canApply: false,
|
|
3359
|
+
pendingPatch: null,
|
|
3360
|
+
quickReplies: [
|
|
3361
|
+
{
|
|
3362
|
+
id: 'explain-current-form',
|
|
3363
|
+
label: 'Explicar formulario atual',
|
|
3364
|
+
prompt: `Explique este formulario considerando: ${prompt}`,
|
|
3365
|
+
kind: 'inline-help',
|
|
3366
|
+
icon: 'help',
|
|
3367
|
+
},
|
|
3368
|
+
],
|
|
3369
|
+
};
|
|
3370
|
+
}
|
|
3371
|
+
optionalJsonObject(value) {
|
|
3372
|
+
if (value === undefined || value === null) {
|
|
3373
|
+
return undefined;
|
|
3374
|
+
}
|
|
3375
|
+
const object = this.toAiJsonObject(value);
|
|
3376
|
+
return Object.keys(object).length ? object : undefined;
|
|
3377
|
+
}
|
|
3378
|
+
mergeJsonObjects(base, overlay) {
|
|
3379
|
+
if (!base)
|
|
3380
|
+
return overlay;
|
|
3381
|
+
if (!overlay)
|
|
3382
|
+
return base;
|
|
3383
|
+
return {
|
|
3384
|
+
...base,
|
|
3385
|
+
...overlay,
|
|
3386
|
+
};
|
|
3387
|
+
}
|
|
3388
|
+
toAiJsonObject(value) {
|
|
3389
|
+
const record = this.toRecord(value);
|
|
3390
|
+
if (!record) {
|
|
3391
|
+
return {};
|
|
3392
|
+
}
|
|
3393
|
+
try {
|
|
3394
|
+
return JSON.parse(JSON.stringify(record));
|
|
3395
|
+
}
|
|
3396
|
+
catch {
|
|
3397
|
+
return {};
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
toRecord(value) {
|
|
3401
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
3402
|
+
? value
|
|
3403
|
+
: null;
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
|
|
2380
3407
|
const SECTION_HEADER_INITIALS_MIN = 1;
|
|
2381
3408
|
const SECTION_HEADER_INITIALS_MAX = 4;
|
|
2382
3409
|
const SECTION_HEADER_INITIALS_DEFAULT = 2;
|
|
@@ -8151,6 +9178,11 @@ class FormAiAdapter extends BaseAiAdapter {
|
|
|
8151
9178
|
}
|
|
8152
9179
|
getAuthoringContext() {
|
|
8153
9180
|
const manifest = PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST;
|
|
9181
|
+
const canAssistRuntimeValues = ((this.host.mode || 'create') === 'create' || this.host.mode === 'edit') &&
|
|
9182
|
+
this.host.effectiveReadonly !== true &&
|
|
9183
|
+
this.host.readonlyModeGlobal !== true;
|
|
9184
|
+
const targetIdentity = this.host.getRuntimeValueTargetIdentity?.();
|
|
9185
|
+
const eligibility = this.host.getRuntimeValueEligibility?.();
|
|
8154
9186
|
return {
|
|
8155
9187
|
authoringContract: {
|
|
8156
9188
|
kind: 'praxis.component-authoring-context',
|
|
@@ -8177,6 +9209,7 @@ class FormAiAdapter extends BaseAiAdapter {
|
|
|
8177
9209
|
canApplyLocalPatch: this.host.enableCustomization === true
|
|
8178
9210
|
&& this.host.effectiveReadonly !== true
|
|
8179
9211
|
&& this.host.readonlyModeGlobal !== true,
|
|
9212
|
+
canAssistRuntimeValues,
|
|
8180
9213
|
reason: this.host.effectiveReadonly === true || this.host.readonlyModeGlobal === true
|
|
8181
9214
|
? 'readonly'
|
|
8182
9215
|
: this.host.enableCustomization === true
|
|
@@ -8185,8 +9218,46 @@ class FormAiAdapter extends BaseAiAdapter {
|
|
|
8185
9218
|
? 'mode=view without customization'
|
|
8186
9219
|
: 'customization-disabled',
|
|
8187
9220
|
},
|
|
9221
|
+
...(targetIdentity
|
|
9222
|
+
? {
|
|
9223
|
+
runtimeValueAssistance: {
|
|
9224
|
+
enabled: canAssistRuntimeValues && (eligibility ? eligibility.eligible : true),
|
|
9225
|
+
targetIdentity,
|
|
9226
|
+
autoSaveEnabled: eligibility?.autoSaveEnabled ?? false,
|
|
9227
|
+
hasPendingReactiveDeterminations: eligibility?.hasPendingReactiveDeterminations ?? false,
|
|
9228
|
+
hasPendingAsyncValidators: eligibility?.hasPendingAsyncValidators ?? false,
|
|
9229
|
+
reactiveDeterminationTargets: (eligibility?.nonOverwritableFields ?? [])
|
|
9230
|
+
.filter((field) => field.reason === 'reactive-determination-target')
|
|
9231
|
+
.map((field) => field.fieldPath),
|
|
9232
|
+
writableFields: eligibility?.writableFields ?? [],
|
|
9233
|
+
nonOverwritableFields: eligibility?.nonOverwritableFields ?? [],
|
|
9234
|
+
defaultApplyMode: 'empty-only',
|
|
9235
|
+
},
|
|
9236
|
+
}
|
|
9237
|
+
: {}),
|
|
8188
9238
|
};
|
|
8189
9239
|
}
|
|
9240
|
+
getRuntimeValueTargetIdentity() {
|
|
9241
|
+
return this.host.getRuntimeValueTargetIdentity?.() ?? null;
|
|
9242
|
+
}
|
|
9243
|
+
getRuntimeValueEligibility() {
|
|
9244
|
+
return this.host.getRuntimeValueEligibility?.() ?? null;
|
|
9245
|
+
}
|
|
9246
|
+
previewRuntimeValues(proposal, options) {
|
|
9247
|
+
return this.host.previewRuntimeValues?.(proposal, options) ?? null;
|
|
9248
|
+
}
|
|
9249
|
+
async applyRuntimeValues(request) {
|
|
9250
|
+
if (!this.host.applyRuntimeValues) {
|
|
9251
|
+
return null;
|
|
9252
|
+
}
|
|
9253
|
+
return await this.host.applyRuntimeValues(request);
|
|
9254
|
+
}
|
|
9255
|
+
async undoRuntimeValues(receiptId) {
|
|
9256
|
+
if (!this.host.undoRuntimeValues) {
|
|
9257
|
+
return null;
|
|
9258
|
+
}
|
|
9259
|
+
return await this.host.undoRuntimeValues(receiptId);
|
|
9260
|
+
}
|
|
8190
9261
|
compileAiResponse(response) {
|
|
8191
9262
|
if (!response || typeof response !== 'object') {
|
|
8192
9263
|
return null;
|
|
@@ -9823,7 +10894,7 @@ class FormRulesService {
|
|
|
9823
10894
|
}
|
|
9824
10895
|
}
|
|
9825
10896
|
resolveComputedRuleFormData(baseFormData, formGroup, formRules, context, result) {
|
|
9826
|
-
|
|
10897
|
+
let formData = { ...baseFormData };
|
|
9827
10898
|
const maxIterations = Math.max(2, formRules.length + 1);
|
|
9828
10899
|
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
9829
10900
|
let changed = false;
|
|
@@ -9852,13 +10923,28 @@ class FormRulesService {
|
|
|
9852
10923
|
if (!this.ruleTargetExists(rule.targetType, normalizedTargetId, formGroup, context.targetIndex)) {
|
|
9853
10924
|
continue;
|
|
9854
10925
|
}
|
|
10926
|
+
const isNested = normalizedTargetId.includes('.');
|
|
10927
|
+
if (isNested && !hasNestedPath(formData, normalizedTargetId)) {
|
|
10928
|
+
continue;
|
|
10929
|
+
}
|
|
9855
10930
|
const valueResult = this.evaluateRuleValue(properties['value'], formData, context);
|
|
9856
10931
|
if (!valueResult.valid) {
|
|
9857
10932
|
continue;
|
|
9858
10933
|
}
|
|
9859
|
-
|
|
9860
|
-
formData
|
|
9861
|
-
|
|
10934
|
+
const currentValue = isNested
|
|
10935
|
+
? getNestedPath(formData, normalizedTargetId)
|
|
10936
|
+
: Object.prototype.hasOwnProperty.call(formData, normalizedTargetId) ? formData[normalizedTargetId] : undefined;
|
|
10937
|
+
if (!this.areRuleValuesEqual(currentValue, valueResult.value)) {
|
|
10938
|
+
if (!isNested) {
|
|
10939
|
+
formData[normalizedTargetId] = valueResult.value;
|
|
10940
|
+
changed = true;
|
|
10941
|
+
continue;
|
|
10942
|
+
}
|
|
10943
|
+
const updatedFormData = setNestedPath(formData, normalizedTargetId, valueResult.value);
|
|
10944
|
+
if (updatedFormData !== formData) {
|
|
10945
|
+
formData = updatedFormData;
|
|
10946
|
+
changed = true;
|
|
10947
|
+
}
|
|
9862
10948
|
}
|
|
9863
10949
|
}
|
|
9864
10950
|
}
|
|
@@ -11794,7 +12880,10 @@ class PraxisDynamicForm {
|
|
|
11794
12880
|
return this.getSectionPresentationPreset(section) === 'compact-presentation';
|
|
11795
12881
|
}
|
|
11796
12882
|
shouldShowContextEmptyState() {
|
|
11797
|
-
if (!this.emptyState
|
|
12883
|
+
if (!this.emptyState)
|
|
12884
|
+
return false;
|
|
12885
|
+
const isEligibleMode = this.mode === 'view' || this.isItemScopedActionSubmitTarget();
|
|
12886
|
+
if (!isEligibleMode)
|
|
11798
12887
|
return false;
|
|
11799
12888
|
if (!this.resourcePath && !this.hasExplicitSchemaUrl() && !this.hasRenderableConfig()) {
|
|
11800
12889
|
return false;
|
|
@@ -11803,6 +12892,126 @@ class PraxisDynamicForm {
|
|
|
11803
12892
|
return false;
|
|
11804
12893
|
return !this.hasLocalRecordContext(this.initialValue);
|
|
11805
12894
|
}
|
|
12895
|
+
isItemScopedActionSubmitTarget() {
|
|
12896
|
+
if (this.schemaSource !== 'action')
|
|
12897
|
+
return false;
|
|
12898
|
+
const rawSubmitUrl = typeof this.submitUrl === 'string' ? this.submitUrl.trim() : '';
|
|
12899
|
+
return rawSubmitUrl.includes('{') || rawSubmitUrl.includes(':id');
|
|
12900
|
+
}
|
|
12901
|
+
getActionTargetRecordSummary() {
|
|
12902
|
+
if (this.schemaSource !== 'action')
|
|
12903
|
+
return null;
|
|
12904
|
+
const record = this.initialValue && typeof this.initialValue === 'object'
|
|
12905
|
+
? this.initialValue
|
|
12906
|
+
: null;
|
|
12907
|
+
const rawId = record?.['id'] ?? this.resourceId;
|
|
12908
|
+
const id = typeof rawId === 'number' && Number.isFinite(rawId)
|
|
12909
|
+
? String(rawId)
|
|
12910
|
+
: typeof rawId === 'string' && rawId.trim().length > 0
|
|
12911
|
+
? rawId.trim()
|
|
12912
|
+
: undefined;
|
|
12913
|
+
if (!id && !record)
|
|
12914
|
+
return null;
|
|
12915
|
+
const titleKeys = [
|
|
12916
|
+
'titulo',
|
|
12917
|
+
'title',
|
|
12918
|
+
'nome',
|
|
12919
|
+
'name',
|
|
12920
|
+
'assunto',
|
|
12921
|
+
'subject',
|
|
12922
|
+
'descricao',
|
|
12923
|
+
'description',
|
|
12924
|
+
'codigo',
|
|
12925
|
+
'code',
|
|
12926
|
+
];
|
|
12927
|
+
const subtitleKeys = [
|
|
12928
|
+
'objetivo',
|
|
12929
|
+
'resumo',
|
|
12930
|
+
'summary',
|
|
12931
|
+
'local',
|
|
12932
|
+
'setor',
|
|
12933
|
+
'departamento',
|
|
12934
|
+
'categoria',
|
|
12935
|
+
'category',
|
|
12936
|
+
];
|
|
12937
|
+
const badgeKeys = [
|
|
12938
|
+
'status',
|
|
12939
|
+
'situacao',
|
|
12940
|
+
'state',
|
|
12941
|
+
'prioridade',
|
|
12942
|
+
'priority',
|
|
12943
|
+
'severidade',
|
|
12944
|
+
'severity',
|
|
12945
|
+
'tipo',
|
|
12946
|
+
'type',
|
|
12947
|
+
'fase',
|
|
12948
|
+
];
|
|
12949
|
+
let title;
|
|
12950
|
+
let subtitle;
|
|
12951
|
+
const badges = [];
|
|
12952
|
+
if (record) {
|
|
12953
|
+
for (const key of titleKeys) {
|
|
12954
|
+
const val = record[key];
|
|
12955
|
+
if (typeof val === 'string' && val.trim().length > 0) {
|
|
12956
|
+
title = val.trim();
|
|
12957
|
+
break;
|
|
12958
|
+
}
|
|
12959
|
+
}
|
|
12960
|
+
for (const key of subtitleKeys) {
|
|
12961
|
+
const val = record[key];
|
|
12962
|
+
if (typeof val === 'string' && val.trim().length > 0 && val.trim() !== title) {
|
|
12963
|
+
subtitle = val.trim();
|
|
12964
|
+
break;
|
|
12965
|
+
}
|
|
12966
|
+
}
|
|
12967
|
+
for (const key of badgeKeys) {
|
|
12968
|
+
if (badges.length >= 2)
|
|
12969
|
+
break;
|
|
12970
|
+
const val = record[key];
|
|
12971
|
+
if (typeof val === 'string' && val.trim().length > 0 && val.trim().length <= 32) {
|
|
12972
|
+
const normalized = val.trim();
|
|
12973
|
+
const upper = normalized.toUpperCase();
|
|
12974
|
+
let tone = 'neutral';
|
|
12975
|
+
if (upper.includes('CRITIC') ||
|
|
12976
|
+
upper.includes('ERRO') ||
|
|
12977
|
+
upper.includes('FALH') ||
|
|
12978
|
+
upper.includes('REJEIT') ||
|
|
12979
|
+
upper.includes('CANCEL') ||
|
|
12980
|
+
upper.includes('BLOQUE')) {
|
|
12981
|
+
tone = 'danger';
|
|
12982
|
+
}
|
|
12983
|
+
else if (upper.includes('ALTA') ||
|
|
12984
|
+
upper.includes('HIGH') ||
|
|
12985
|
+
upper.includes('ALERT') ||
|
|
12986
|
+
upper.includes('PENDENT') ||
|
|
12987
|
+
upper.includes('AGUARD')) {
|
|
12988
|
+
tone = 'warning';
|
|
12989
|
+
}
|
|
12990
|
+
else if (upper.includes('APROV') ||
|
|
12991
|
+
upper.includes('CONCLU') ||
|
|
12992
|
+
upper.includes('ATIV') ||
|
|
12993
|
+
upper.includes('OK') ||
|
|
12994
|
+
upper.includes('DONE')) {
|
|
12995
|
+
tone = 'success';
|
|
12996
|
+
}
|
|
12997
|
+
else if (upper.includes('PLANEJ') ||
|
|
12998
|
+
upper.includes('ANDAMENTO') ||
|
|
12999
|
+
upper.includes('INICI') ||
|
|
13000
|
+
upper.includes('ABERT')) {
|
|
13001
|
+
tone = 'info';
|
|
13002
|
+
}
|
|
13003
|
+
badges.push({
|
|
13004
|
+
label: key,
|
|
13005
|
+
value: normalized.replace(/_/g, ' '),
|
|
13006
|
+
tone,
|
|
13007
|
+
});
|
|
13008
|
+
}
|
|
13009
|
+
}
|
|
13010
|
+
}
|
|
13011
|
+
if (!id && !title && badges.length === 0)
|
|
13012
|
+
return null;
|
|
13013
|
+
return { id, title, subtitle, badges };
|
|
13014
|
+
}
|
|
11806
13015
|
hasResourceContext(value) {
|
|
11807
13016
|
return typeof value === 'number'
|
|
11808
13017
|
? Number.isFinite(value)
|
|
@@ -11824,7 +13033,11 @@ class PraxisDynamicForm {
|
|
|
11824
13033
|
return this.disabledModeGlobal === null ? null : this.disabledModeGlobal === true;
|
|
11825
13034
|
}
|
|
11826
13035
|
get effectiveFormIsValid() {
|
|
11827
|
-
return !this.entityHydrationPending &&
|
|
13036
|
+
return (!this.entityHydrationPending &&
|
|
13037
|
+
!this.entityReadFailed &&
|
|
13038
|
+
!this.form.invalid &&
|
|
13039
|
+
!this.form.pending &&
|
|
13040
|
+
this.form.status === 'VALID');
|
|
11828
13041
|
}
|
|
11829
13042
|
get configControlLabel() {
|
|
11830
13043
|
return this.schemaOutdated
|
|
@@ -12142,6 +13355,8 @@ class PraxisDynamicForm {
|
|
|
12142
13355
|
(error.name === 'TimeoutError' || error.name === 'AbortError');
|
|
12143
13356
|
}
|
|
12144
13357
|
schemaCache = null;
|
|
13358
|
+
schemaValidationFailed = false;
|
|
13359
|
+
initialValueContextInvalidated = false;
|
|
12145
13360
|
lastSchemaMeta;
|
|
12146
13361
|
schemaMetaPersistenceQueues = new Map();
|
|
12147
13362
|
persistenceContextEpoch = 0;
|
|
@@ -12169,6 +13384,14 @@ class PraxisDynamicForm {
|
|
|
12169
13384
|
entityReadCancel$ = new Subject();
|
|
12170
13385
|
isDestroyed = false;
|
|
12171
13386
|
formValueChangesSubscription = null;
|
|
13387
|
+
formStatusChangesSubscription = null;
|
|
13388
|
+
runtimeValueJournal = new PraxisRuntimeFormValueSessionJournal();
|
|
13389
|
+
runtimeValueRevision = 0;
|
|
13390
|
+
runtimeValueTrackedForm = null;
|
|
13391
|
+
runtimeValueTrackedControls = new Map();
|
|
13392
|
+
suppressCommandRuleSideEffectsDepth = 0;
|
|
13393
|
+
pendingSuppressedCommandEvaluation = false;
|
|
13394
|
+
consumingSuppressedCommandEvaluation = false;
|
|
12172
13395
|
submitFieldErrorSubscriptions = new Map();
|
|
12173
13396
|
activeSubmitErrorDetails = [];
|
|
12174
13397
|
reactiveDeterminationSubscription = null;
|
|
@@ -13149,6 +14372,12 @@ class PraxisDynamicForm {
|
|
|
13149
14372
|
this.loadedEntityData = null;
|
|
13150
14373
|
this.hydratedEntityId = null;
|
|
13151
14374
|
this.entityHydrationPending = false;
|
|
14375
|
+
if (this.hasSchemaBackedRuntime()) {
|
|
14376
|
+
this.runtimeFieldMetadata = null;
|
|
14377
|
+
this.initialValueContextInvalidated = true;
|
|
14378
|
+
this.retryInitialization();
|
|
14379
|
+
return;
|
|
14380
|
+
}
|
|
13152
14381
|
}
|
|
13153
14382
|
this.runtimeFieldMetadata = null;
|
|
13154
14383
|
if (this.hasBuiltFormFromConfig && this.hasRenderableConfig()) {
|
|
@@ -13290,6 +14519,9 @@ class PraxisDynamicForm {
|
|
|
13290
14519
|
}
|
|
13291
14520
|
}
|
|
13292
14521
|
ngOnChanges(changes) {
|
|
14522
|
+
if (changes['initialValue']) {
|
|
14523
|
+
this.initialValueContextInvalidated = false;
|
|
14524
|
+
}
|
|
13293
14525
|
const configChange = changes['config'];
|
|
13294
14526
|
const configInputChanged = !!configChange && (configChange.firstChange ||
|
|
13295
14527
|
!this.isEquivalentFormConfig(configChange.previousValue, configChange.currentValue));
|
|
@@ -13659,6 +14891,8 @@ class PraxisDynamicForm {
|
|
|
13659
14891
|
catch (error) {
|
|
13660
14892
|
if (!current() || initializationCycle !== this.schemaInitializationCycle || error instanceof PraxisDynamicFormDestroyedError)
|
|
13661
14893
|
return;
|
|
14894
|
+
if (this.hasInitializationError())
|
|
14895
|
+
return;
|
|
13662
14896
|
this.errorLog('[PDF] initializeForm:error', error);
|
|
13663
14897
|
const key = this.formConfigKey();
|
|
13664
14898
|
const hasLocalConfig = key
|
|
@@ -13683,22 +14917,27 @@ class PraxisDynamicForm {
|
|
|
13683
14917
|
}
|
|
13684
14918
|
}
|
|
13685
14919
|
}
|
|
14920
|
+
hasInitializationError() {
|
|
14921
|
+
return this.initializationStatus === 'error';
|
|
14922
|
+
}
|
|
13686
14923
|
handleInitializationError(stage, error, context) {
|
|
13687
14924
|
if (this.isDestroyed || error instanceof PraxisDynamicFormDestroyedError)
|
|
13688
14925
|
return;
|
|
13689
14926
|
this.initializationStatus = 'error';
|
|
14927
|
+
this.isInitialized = false;
|
|
13690
14928
|
this.isLoading = false;
|
|
13691
14929
|
this.cdr.detectChanges();
|
|
13692
14930
|
const formError = {
|
|
13693
14931
|
stage,
|
|
13694
14932
|
error,
|
|
13695
14933
|
context,
|
|
13696
|
-
recoverable: stage !== 'config-load'
|
|
14934
|
+
recoverable: stage !== 'config-load' && !this.requiresConfirmedSchemaContext() &&
|
|
14935
|
+
![401, 403].includes(Number(error.status)),
|
|
13697
14936
|
userMessage: this.getErrorMessage(stage, error),
|
|
13698
14937
|
};
|
|
13699
14938
|
// Update UX state
|
|
13700
14939
|
this.currentErrorMessage = formError.userMessage;
|
|
13701
|
-
this.currentErrorDetails = { stage, error: error.message, context };
|
|
14940
|
+
this.currentErrorDetails = { stage, error: error.message, status: error.status, context };
|
|
13702
14941
|
this.isRecoverable = formError.recoverable;
|
|
13703
14942
|
this.errorLog(`[PraxisDynamicForm] Initialization error at ${stage}:`, error);
|
|
13704
14943
|
this.initializationError.emit(formError);
|
|
@@ -13728,6 +14967,15 @@ class PraxisDynamicForm {
|
|
|
13728
14967
|
return String(field.name || '').replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
13729
14968
|
}
|
|
13730
14969
|
getErrorMessage(stage, error) {
|
|
14970
|
+
if (stage === 'schema-fetch' && this.requiresConfirmedSchemaContext()) {
|
|
14971
|
+
return this.i18n.t('runtime.schemaRead.contextRequired', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
14972
|
+
}
|
|
14973
|
+
if ([401, 403].includes(Number(error.status))) {
|
|
14974
|
+
return this.i18n.t('runtime.schemaRead.denied', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
14975
|
+
}
|
|
14976
|
+
if (stage === 'schema-fetch' && this.schemaValidationFailed) {
|
|
14977
|
+
return this.i18n.t('runtime.schemaRead.invalid', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
14978
|
+
}
|
|
13731
14979
|
if (stage === 'schema-fetch' && error.name === 'TimeoutError') {
|
|
13732
14980
|
return this.i18n.t('runtime.schemaRead.timeout', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
13733
14981
|
}
|
|
@@ -13822,10 +15070,9 @@ class PraxisDynamicForm {
|
|
|
13822
15070
|
this.assertSchemaInitializationCurrent(cycle);
|
|
13823
15071
|
if (!current())
|
|
13824
15072
|
return;
|
|
15073
|
+
if (!Array.isArray(serverDefs))
|
|
15074
|
+
throw new Error('Invalid schema field metadata.');
|
|
13825
15075
|
const fieldMetadata = mapFieldDefinitionsToMetadata(serverDefs);
|
|
13826
|
-
if (!fieldMetadata || fieldMetadata.length === 0) {
|
|
13827
|
-
throw new Error('No field metadata received from server');
|
|
13828
|
-
}
|
|
13829
15076
|
// Generate default layout from metadata (padrão: 2 campos por linha)
|
|
13830
15077
|
const hostConfig = normalizeFormConfig$1(this.config);
|
|
13831
15078
|
if (this.shouldUseSchemaLayoutPolicy()) {
|
|
@@ -13885,9 +15132,8 @@ class PraxisDynamicForm {
|
|
|
13885
15132
|
this.assertSchemaInitializationCurrent(cycle);
|
|
13886
15133
|
if (!current())
|
|
13887
15134
|
return;
|
|
13888
|
-
if (!serverDefs
|
|
13889
|
-
throw new Error('
|
|
13890
|
-
}
|
|
15135
|
+
if (!Array.isArray(serverDefs))
|
|
15136
|
+
throw new Error('Invalid schema field metadata.');
|
|
13891
15137
|
const hostConfig = normalizeFormConfig$1(this.config);
|
|
13892
15138
|
this.effectiveConfig = this.shouldUseSchemaLayoutPolicy()
|
|
13893
15139
|
? this.createSchemaMaterializedConfig(hostConfig, mapFieldDefinitionsToMetadata(serverDefs))
|
|
@@ -13969,13 +15215,13 @@ class PraxisDynamicForm {
|
|
|
13969
15215
|
const cycle = this.schemaInitializationCycle;
|
|
13970
15216
|
const current = this.persistenceGuard(true);
|
|
13971
15217
|
try {
|
|
15218
|
+
this.schemaCache = null;
|
|
13972
15219
|
const serverDefs = await this.getSchemaWithCache();
|
|
13973
15220
|
this.assertSchemaInitializationCurrent(cycle);
|
|
13974
15221
|
if (!current())
|
|
13975
15222
|
return;
|
|
13976
|
-
if (!serverDefs
|
|
13977
|
-
|
|
13978
|
-
}
|
|
15223
|
+
if (!Array.isArray(serverDefs))
|
|
15224
|
+
throw new Error('Invalid schema field metadata.');
|
|
13979
15225
|
const before = JSON.stringify(this.config);
|
|
13980
15226
|
this.effectiveConfig = normalizeFormConfig$1(reconcileFormConfig(this.config, serverDefs));
|
|
13981
15227
|
if (this.schemaRootHooks) {
|
|
@@ -14001,7 +15247,10 @@ class PraxisDynamicForm {
|
|
|
14001
15247
|
return;
|
|
14002
15248
|
if (this.isSchemaTransportInterruption(error) || error instanceof PraxisDynamicFormDestroyedError)
|
|
14003
15249
|
throw error;
|
|
14004
|
-
this.
|
|
15250
|
+
this.handleInitializationError('schema-fetch', error, {
|
|
15251
|
+
formId: this.formId, resourcePath: this.resourcePath, hasLocalConfig: true,
|
|
15252
|
+
});
|
|
15253
|
+
throw error;
|
|
14005
15254
|
}
|
|
14006
15255
|
}
|
|
14007
15256
|
hostConfigHasAuthoredLocalFieldsNotInLocalConfig(hostConfig, localConfig) {
|
|
@@ -14014,8 +15263,14 @@ class PraxisDynamicForm {
|
|
|
14014
15263
|
}
|
|
14015
15264
|
async syncWithServer() {
|
|
14016
15265
|
// Deprecated by verify-only flow; keeping for manual reconcile paths
|
|
15266
|
+
const cycle = this.schemaInitializationCycle;
|
|
15267
|
+
const current = this.persistenceGuard(true);
|
|
14017
15268
|
try {
|
|
15269
|
+
this.schemaCache = null;
|
|
14018
15270
|
const serverDefs = await this.getSchemaWithCache();
|
|
15271
|
+
this.assertSchemaInitializationCurrent(cycle);
|
|
15272
|
+
if (!current())
|
|
15273
|
+
return;
|
|
14019
15274
|
const serverMetadata = mapFieldDefinitionsToMetadata(serverDefs);
|
|
14020
15275
|
const syncResult = syncWithServerMetadata(this.config, serverMetadata);
|
|
14021
15276
|
this.effectiveConfig = syncResult.config;
|
|
@@ -14038,13 +15293,16 @@ class PraxisDynamicForm {
|
|
|
14038
15293
|
}
|
|
14039
15294
|
}
|
|
14040
15295
|
catch (error) {
|
|
14041
|
-
|
|
14042
|
-
|
|
15296
|
+
if (!current())
|
|
15297
|
+
return;
|
|
15298
|
+
if (this.isSchemaTransportInterruption(error) || error instanceof PraxisDynamicFormDestroyedError)
|
|
15299
|
+
throw error;
|
|
15300
|
+
this.handleInitializationError('schema-fetch', error, {
|
|
14043
15301
|
formId: this.formId,
|
|
14044
15302
|
resourcePath: this.resourcePath,
|
|
14045
15303
|
hasLocalConfig: true,
|
|
14046
15304
|
});
|
|
14047
|
-
|
|
15305
|
+
throw error;
|
|
14048
15306
|
}
|
|
14049
15307
|
}
|
|
14050
15308
|
isActionCommandWithoutExplicitReadUrl() {
|
|
@@ -14188,7 +15446,12 @@ class PraxisDynamicForm {
|
|
|
14188
15446
|
this.entityHydrationPending = false;
|
|
14189
15447
|
this.entityReadFailed = false;
|
|
14190
15448
|
if (Object.keys(this.form.controls || {}).length) {
|
|
14191
|
-
this.
|
|
15449
|
+
if (this.mode === 'create') {
|
|
15450
|
+
this.form.reset(normalized, { emitEvent: false });
|
|
15451
|
+
}
|
|
15452
|
+
else {
|
|
15453
|
+
this.form.patchValue(normalized, { emitEvent: false });
|
|
15454
|
+
}
|
|
14192
15455
|
}
|
|
14193
15456
|
this.hydratedEntityId = this.pendingEntityId;
|
|
14194
15457
|
this.debugLog('[PDF] loadEntity:initialValue', { id: this.pendingEntityId });
|
|
@@ -14266,7 +15529,15 @@ class PraxisDynamicForm {
|
|
|
14266
15529
|
}
|
|
14267
15530
|
this.suppressedValueChangeBuildId = 0;
|
|
14268
15531
|
}
|
|
14269
|
-
this.
|
|
15532
|
+
const consumeSuppressed = this.pendingSuppressedCommandEvaluation;
|
|
15533
|
+
this.pendingSuppressedCommandEvaluation = false;
|
|
15534
|
+
this.consumingSuppressedCommandEvaluation = consumeSuppressed;
|
|
15535
|
+
try {
|
|
15536
|
+
this.evaluateAndApplyRules();
|
|
15537
|
+
}
|
|
15538
|
+
finally {
|
|
15539
|
+
this.consumingSuppressedCommandEvaluation = false;
|
|
15540
|
+
}
|
|
14270
15541
|
if (this.isReactiveValidationEnabled()) {
|
|
14271
15542
|
try {
|
|
14272
15543
|
this.reactiveValidate$?.next();
|
|
@@ -14283,6 +15554,12 @@ class PraxisDynamicForm {
|
|
|
14283
15554
|
});
|
|
14284
15555
|
this.emitPayloadPreview('value-change', currentValues, dirtyFields);
|
|
14285
15556
|
});
|
|
15557
|
+
this.formStatusChangesSubscription = this.form.statusChanges
|
|
15558
|
+
.pipe(takeUntil(this.destroy$))
|
|
15559
|
+
.subscribe(() => {
|
|
15560
|
+
this.cdr.markForCheck();
|
|
15561
|
+
});
|
|
15562
|
+
this.ensureRuntimeValueTracking();
|
|
14286
15563
|
this.formReady.emit({
|
|
14287
15564
|
formGroup: this.form,
|
|
14288
15565
|
fieldsMetadata: fieldMetadata,
|
|
@@ -14310,6 +15587,9 @@ class PraxisDynamicForm {
|
|
|
14310
15587
|
resetFormValueChangesSubscription(buildCycleId) {
|
|
14311
15588
|
this.formValueChangesSubscription?.unsubscribe();
|
|
14312
15589
|
this.formValueChangesSubscription = null;
|
|
15590
|
+
this.formStatusChangesSubscription?.unsubscribe();
|
|
15591
|
+
this.formStatusChangesSubscription = null;
|
|
15592
|
+
this.clearRuntimeValueControlSubscriptions();
|
|
14313
15593
|
this.suppressedValueChangeBuildId = buildCycleId;
|
|
14314
15594
|
this.pendingBootstrapValueChangeBuildId = 0;
|
|
14315
15595
|
}
|
|
@@ -14568,13 +15848,12 @@ class PraxisDynamicForm {
|
|
|
14568
15848
|
return null;
|
|
14569
15849
|
}
|
|
14570
15850
|
const dirtyFields = this.getDirtyFieldNames();
|
|
14571
|
-
const touchedFields =
|
|
14572
|
-
|
|
14573
|
-
.map(([fieldName]) => fieldName);
|
|
15851
|
+
const touchedFields = new Set();
|
|
15852
|
+
this.collectTouchedFieldNames(this.form, '', touchedFields);
|
|
14574
15853
|
return {
|
|
14575
15854
|
rawValue: this.form.getRawValue(),
|
|
14576
15855
|
dirtyFields,
|
|
14577
|
-
touchedFields,
|
|
15856
|
+
touchedFields: Array.from(touchedFields),
|
|
14578
15857
|
context: this.buildCurrentFormRuntimeContext(),
|
|
14579
15858
|
};
|
|
14580
15859
|
}
|
|
@@ -14597,11 +15876,24 @@ class PraxisDynamicForm {
|
|
|
14597
15876
|
if (!this.form || !Object.keys(this.form.controls || {}).length) {
|
|
14598
15877
|
return;
|
|
14599
15878
|
}
|
|
15879
|
+
let formData;
|
|
15880
|
+
let isValid = this.form.valid;
|
|
15881
|
+
try {
|
|
15882
|
+
formData = this.prepareCurrentSubmitPayload(rawFormData, dirtyFields);
|
|
15883
|
+
}
|
|
15884
|
+
catch (error) {
|
|
15885
|
+
if (!(error instanceof TypeError))
|
|
15886
|
+
throw error;
|
|
15887
|
+
// Invalid scalar input remains available as raw diagnostics, never as a
|
|
15888
|
+
// payload that a preview consumer could apply.
|
|
15889
|
+
formData = null;
|
|
15890
|
+
isValid = false;
|
|
15891
|
+
}
|
|
14600
15892
|
this.payloadPreviewChange.emit({
|
|
14601
|
-
formData
|
|
15893
|
+
formData,
|
|
14602
15894
|
rawFormData,
|
|
14603
15895
|
changedFields: dirtyFields,
|
|
14604
|
-
isValid
|
|
15896
|
+
isValid,
|
|
14605
15897
|
entityId: this.resourceId ?? undefined,
|
|
14606
15898
|
operation: this.resolveSubmitOperation(),
|
|
14607
15899
|
reason,
|
|
@@ -14648,6 +15940,15 @@ class PraxisDynamicForm {
|
|
|
14648
15940
|
this.collectDirtyFieldNames(childControl, childPath, dirtyFields);
|
|
14649
15941
|
}
|
|
14650
15942
|
}
|
|
15943
|
+
collectTouchedFieldNames(control, path, fields) {
|
|
15944
|
+
const children = control.controls;
|
|
15945
|
+
for (const [name, child] of Object.entries(children ?? {})) {
|
|
15946
|
+
const childPath = path ? `${path}.${name}` : name;
|
|
15947
|
+
if (child.touched)
|
|
15948
|
+
fields.add(childPath);
|
|
15949
|
+
this.collectTouchedFieldNames(child, childPath, fields);
|
|
15950
|
+
}
|
|
15951
|
+
}
|
|
14651
15952
|
buildCurrentFormRuntimeContext() {
|
|
14652
15953
|
const resourcePath = (this.resourcePath || '').trim();
|
|
14653
15954
|
return {
|
|
@@ -14691,11 +15992,22 @@ class PraxisDynamicForm {
|
|
|
14691
15992
|
(this.resourceId ?? this.pendingEntityId ?? null)
|
|
14692
15993
|
? this.loadedEntityData
|
|
14693
15994
|
: null;
|
|
14694
|
-
const
|
|
15995
|
+
const authoritativeCreateSeed = this.mode === 'create' && !fallbackEntityValue
|
|
14695
15996
|
? this.getNormalizedInitialValue()
|
|
14696
15997
|
: null;
|
|
15998
|
+
const fallbackInitialValue = !snapshotValue && !fallbackEntityValue
|
|
15999
|
+
? (authoritativeCreateSeed ?? this.getNormalizedInitialValue())
|
|
16000
|
+
: null;
|
|
14697
16001
|
const valueToRestore = snapshotValue ?? fallbackEntityValue ?? fallbackInitialValue;
|
|
14698
|
-
if (
|
|
16002
|
+
if (this.mode === 'create' && authoritativeCreateSeed && !fallbackEntityValue) {
|
|
16003
|
+
// A supplied create seed is authoritative, including empty objects,
|
|
16004
|
+
// omissions, and subsequent metadata rebuilds. Do not fill cleared or
|
|
16005
|
+
// newly added business fields from schema defaults.
|
|
16006
|
+
this.form.reset(snapshotValue
|
|
16007
|
+
? { ...authoritativeCreateSeed, ...this.normalizeFormPatchValue(snapshotValue) }
|
|
16008
|
+
: authoritativeCreateSeed, { emitEvent: false });
|
|
16009
|
+
}
|
|
16010
|
+
else if (valueToRestore) {
|
|
14699
16011
|
this.form.patchValue(this.normalizeFormPatchValue(valueToRestore), { emitEvent: false });
|
|
14700
16012
|
}
|
|
14701
16013
|
if (!previousState ||
|
|
@@ -14711,15 +16023,20 @@ class PraxisDynamicForm {
|
|
|
14711
16023
|
}
|
|
14712
16024
|
}
|
|
14713
16025
|
getNormalizedInitialValue() {
|
|
16026
|
+
if (this.initialValueContextInvalidated)
|
|
16027
|
+
return null;
|
|
14714
16028
|
// A seed from the former remote record cannot resurrect a cleared selection.
|
|
14715
16029
|
// Local projections and create commands still own their initialValue snapshot.
|
|
14716
16030
|
if (this.entitySelectionCleared && !this.usesInitialValueAsAuthoritativeSnapshot())
|
|
14717
16031
|
return null;
|
|
14718
|
-
|
|
16032
|
+
const rawSeed = this.initialValue && typeof this.initialValue === 'object' && !Array.isArray(this.initialValue)
|
|
16033
|
+
? this.initialValue
|
|
16034
|
+
: null;
|
|
16035
|
+
if (!rawSeed || typeof rawSeed !== 'object') {
|
|
14719
16036
|
return null;
|
|
14720
16037
|
}
|
|
14721
|
-
const normalized = this.normalizeFormPatchValue(
|
|
14722
|
-
return Object.keys(normalized || {}).length ? normalized : null;
|
|
16038
|
+
const normalized = this.normalizeFormPatchValue(rawSeed);
|
|
16039
|
+
return this.mode === 'create' || Object.keys(normalized || {}).length ? normalized : null;
|
|
14723
16040
|
}
|
|
14724
16041
|
/**
|
|
14725
16042
|
* A local composition owns the complete snapshot supplied through initialValue.
|
|
@@ -14733,20 +16050,25 @@ class PraxisDynamicForm {
|
|
|
14733
16050
|
return !String(this.readUrl || '').trim() && !String(this.resourcePath || '').trim();
|
|
14734
16051
|
}
|
|
14735
16052
|
normalizeFormPatchValue(value) {
|
|
14736
|
-
const
|
|
16053
|
+
const fieldMetadata = this.config?.fieldMetadata || [];
|
|
16054
|
+
const normalized = normalizeDateArrays(value, fieldMetadata);
|
|
14737
16055
|
if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) {
|
|
14738
16056
|
return normalized;
|
|
14739
16057
|
}
|
|
14740
|
-
const fieldMetadata = this.config?.fieldMetadata || [];
|
|
14741
16058
|
if (!fieldMetadata.length) {
|
|
14742
16059
|
return normalized;
|
|
14743
16060
|
}
|
|
14744
|
-
|
|
16061
|
+
let result = { ...normalized };
|
|
14745
16062
|
for (const field of fieldMetadata) {
|
|
14746
|
-
if (!field?.name || !this.isDateControlMetadata(field) || !(field.name
|
|
16063
|
+
if (!field?.name || !this.isDateControlMetadata(field) || !hasNestedPath(result, field.name)) {
|
|
16064
|
+
continue;
|
|
16065
|
+
}
|
|
16066
|
+
const value = this.coerceDateControlValue(getNestedPath(result, field.name));
|
|
16067
|
+
if (!field.name.includes('.')) {
|
|
16068
|
+
result[field.name] = value;
|
|
14747
16069
|
continue;
|
|
14748
16070
|
}
|
|
14749
|
-
result
|
|
16071
|
+
result = setNestedPath(result, field.name, value);
|
|
14750
16072
|
}
|
|
14751
16073
|
return result;
|
|
14752
16074
|
}
|
|
@@ -15237,6 +16559,10 @@ class PraxisDynamicForm {
|
|
|
15237
16559
|
}
|
|
15238
16560
|
state.deliveredKeys.add(distinctKey);
|
|
15239
16561
|
state.lastDeliveredAt = Date.now();
|
|
16562
|
+
if (this.suppressCommandRuleSideEffectsDepth > 0 ||
|
|
16563
|
+
this.consumingSuppressedCommandEvaluation) {
|
|
16564
|
+
return;
|
|
16565
|
+
}
|
|
15240
16566
|
void this.executeFormCommandGlobalAction(rule?.id || ruleKey, effectId, effectRef, formData);
|
|
15241
16567
|
});
|
|
15242
16568
|
}
|
|
@@ -15594,9 +16920,24 @@ class PraxisDynamicForm {
|
|
|
15594
16920
|
}
|
|
15595
16921
|
return eligibleSections[eligibleSections.length - 1];
|
|
15596
16922
|
}
|
|
16923
|
+
get actionTargetSelectedRecordLabel() {
|
|
16924
|
+
return this.i18n.t('runtime.actionTarget.selectedRecord', undefined, 'Registro selecionado', PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
16925
|
+
}
|
|
15597
16926
|
getSectionTitle(section) {
|
|
15598
16927
|
const props = this.getSectionRuleProps(section);
|
|
15599
|
-
|
|
16928
|
+
if (props.title !== undefined) {
|
|
16929
|
+
return props.title;
|
|
16930
|
+
}
|
|
16931
|
+
const rawSectionTitle = section.title;
|
|
16932
|
+
const defaultTitle = this.i18n.t('layout.defaultSectionTitle', undefined, 'Informações', PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
16933
|
+
if ((!rawSectionTitle || rawSectionTitle === 'Informações' || rawSectionTitle === defaultTitle) &&
|
|
16934
|
+
(this.config?.sections?.length ?? 0) === 1) {
|
|
16935
|
+
const hostTitle = this.config?.title;
|
|
16936
|
+
if (typeof hostTitle === 'string' && hostTitle.trim().length > 0) {
|
|
16937
|
+
return hostTitle.trim();
|
|
16938
|
+
}
|
|
16939
|
+
}
|
|
16940
|
+
return rawSectionTitle;
|
|
15600
16941
|
}
|
|
15601
16942
|
getSectionDescription(section) {
|
|
15602
16943
|
const props = this.getSectionRuleProps(section);
|
|
@@ -16851,6 +18192,8 @@ class PraxisDynamicForm {
|
|
|
16851
18192
|
undefined);
|
|
16852
18193
|
}
|
|
16853
18194
|
async onSubmit() {
|
|
18195
|
+
if (this.hasSchemaBackedRuntime() && (this.isLoading || this.initializationStatus === 'error' || this.requiresConfirmedSchemaContext()))
|
|
18196
|
+
return;
|
|
16854
18197
|
if (this.effectiveReadonly || this.effectivePresentation)
|
|
16855
18198
|
return;
|
|
16856
18199
|
if (this.isDestroyed || this.submitting || this.submitPreparationInProgress)
|
|
@@ -16879,6 +18222,8 @@ class PraxisDynamicForm {
|
|
|
16879
18222
|
const preparationIsCurrent = () => {
|
|
16880
18223
|
if (this.isDestroyed)
|
|
16881
18224
|
return false;
|
|
18225
|
+
if (this.hasSchemaBackedRuntime() && (this.isLoading || this.initializationStatus === 'error' || this.requiresConfirmedSchemaContext()))
|
|
18226
|
+
return false;
|
|
16882
18227
|
if (!automatic || this.isResourceRevisionCurrent(binding, epoch))
|
|
16883
18228
|
return true;
|
|
16884
18229
|
// A previously started hook can still hold the reused group. Its draft is no longer authoritative.
|
|
@@ -16907,10 +18252,12 @@ class PraxisDynamicForm {
|
|
|
16907
18252
|
return;
|
|
16908
18253
|
if (!(await waitForCurrentPreparation()))
|
|
16909
18254
|
return;
|
|
16910
|
-
if (this.form.invalid) {
|
|
18255
|
+
if (this.form.invalid || this.form.pending || this.form.status !== 'VALID') {
|
|
16911
18256
|
// UX: marcar todos como touched para exibir erros
|
|
16912
18257
|
this.form.markAllAsTouched();
|
|
16913
|
-
this.form.
|
|
18258
|
+
if (!this.form.pending) {
|
|
18259
|
+
this.form.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
|
18260
|
+
}
|
|
16914
18261
|
// UX Corporativa: Em layout por abas, se a aba ativa não tem erros, navega até a primeira aba com erro
|
|
16915
18262
|
if (this.effectiveLayoutMode === 'tabs' && this.effectiveTabs.length > 0) {
|
|
16916
18263
|
const currentTabHasErrors = this.effectiveTabs.some((t) => t.id === this.activeTabId && this.getTabErrorCount(t) > 0);
|
|
@@ -16994,9 +18341,11 @@ class PraxisDynamicForm {
|
|
|
16994
18341
|
return;
|
|
16995
18342
|
if (!(await waitForCurrentPreparation()))
|
|
16996
18343
|
return;
|
|
16997
|
-
if (this.form.invalid) {
|
|
18344
|
+
if (this.form.invalid || this.form.pending || this.form.status !== 'VALID') {
|
|
16998
18345
|
this.form.markAllAsTouched();
|
|
16999
|
-
this.form.
|
|
18346
|
+
if (!this.form.pending) {
|
|
18347
|
+
this.form.updateValueAndValidity({ onlySelf: false, emitEvent: false });
|
|
18348
|
+
}
|
|
17000
18349
|
return;
|
|
17001
18350
|
}
|
|
17002
18351
|
// Snapshot after hooks potentially changed control values
|
|
@@ -17343,8 +18692,8 @@ class PraxisDynamicForm {
|
|
|
17343
18692
|
this.cdr.markForCheck();
|
|
17344
18693
|
});
|
|
17345
18694
|
}
|
|
17346
|
-
onAiAssistantApply() {
|
|
17347
|
-
this.aiAssistantController?.apply().subscribe((state) => {
|
|
18695
|
+
onAiAssistantApply(contextHints) {
|
|
18696
|
+
this.aiAssistantController?.apply(contextHints ?? undefined).subscribe((state) => {
|
|
17348
18697
|
this.aiAssistantViewState = state;
|
|
17349
18698
|
this.syncAiAssistantSession();
|
|
17350
18699
|
this.cdr.markForCheck();
|
|
@@ -17415,32 +18764,22 @@ class PraxisDynamicForm {
|
|
|
17415
18764
|
initializeAiAssistantController() {
|
|
17416
18765
|
if (this.aiAssistantController)
|
|
17417
18766
|
return;
|
|
17418
|
-
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
|
|
17426
|
-
|
|
17427
|
-
|
|
17428
|
-
|
|
17429
|
-
this.
|
|
17430
|
-
this.
|
|
17431
|
-
this.aiAssistantStateSubscription?.unsubscribe();
|
|
17432
|
-
this.aiAssistantStateSubscription = controller.state$.subscribe((state) => {
|
|
17433
|
-
this.aiAssistantViewState = state;
|
|
17434
|
-
this.syncAiAssistantSession();
|
|
17435
|
-
this.cdr.markForCheck();
|
|
17436
|
-
});
|
|
18767
|
+
const flow = new DynamicFormAgenticAuthoringTurnFlow(this.aiAdapter, this.agenticTurnClient);
|
|
18768
|
+
const controller = this.aiTurnOrchestrator.createController(flow, {
|
|
18769
|
+
componentId: this.aiAdapter.componentId || 'praxis-dynamic-form',
|
|
18770
|
+
componentType: this.aiAdapter.componentType || 'form',
|
|
18771
|
+
sessionId: this.resolveAiAssistantSessionId(),
|
|
18772
|
+
contextItems: this.buildAiAssistantContextItems(),
|
|
18773
|
+
});
|
|
18774
|
+
this.aiAssistantController = controller;
|
|
18775
|
+
this.aiAssistantViewState = controller.snapshot();
|
|
18776
|
+
this.aiAssistantStateSubscription?.unsubscribe();
|
|
18777
|
+
this.aiAssistantStateSubscription = controller.state$.subscribe((state) => {
|
|
18778
|
+
this.aiAssistantViewState = state;
|
|
18779
|
+
this.syncAiAssistantSession();
|
|
17437
18780
|
this.cdr.markForCheck();
|
|
17438
|
-
})
|
|
17439
|
-
.catch((error) => {
|
|
17440
|
-
this.warnLog('[PraxisDynamicForm] Failed to initialize AI assistant turn flow.', {
|
|
17441
|
-
error: error instanceof Error ? error.message : String(error || 'unknown'),
|
|
17442
|
-
});
|
|
17443
18781
|
});
|
|
18782
|
+
this.cdr.markForCheck();
|
|
17444
18783
|
}
|
|
17445
18784
|
buildAiAssistantContextItems() {
|
|
17446
18785
|
const items = [
|
|
@@ -17520,7 +18859,7 @@ class PraxisDynamicForm {
|
|
|
17520
18859
|
value: item.value || '',
|
|
17521
18860
|
kind: item.kind,
|
|
17522
18861
|
})),
|
|
17523
|
-
mode: this.enableCustomization
|
|
18862
|
+
mode: (this.enableCustomization || !this.effectiveReadonly) ? 'agentic-authoring' : 'inline-help',
|
|
17524
18863
|
authoringManifestRef: {
|
|
17525
18864
|
componentId: 'praxis-dynamic-form',
|
|
17526
18865
|
source: 'PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST',
|
|
@@ -17556,7 +18895,7 @@ class PraxisDynamicForm {
|
|
|
17556
18895
|
this.assistantSessions.upsertContextSession(this.buildAiAssistantContextSnapshot(), {
|
|
17557
18896
|
title: 'Copiloto semantico Praxis',
|
|
17558
18897
|
summary: this.resolveAiAssistantSummary(),
|
|
17559
|
-
mode: state?.mode || (this.enableCustomization ? 'agentic-authoring' : 'inline-help'),
|
|
18898
|
+
mode: state?.mode || ((this.enableCustomization || !this.effectiveReadonly) ? 'agentic-authoring' : 'inline-help'),
|
|
17560
18899
|
state: state?.state || 'idle',
|
|
17561
18900
|
visibility: visibility ?? (this.aiAssistantOpen ? 'active' : 'minimized'),
|
|
17562
18901
|
badge: this.resolveAiAssistantBadge(),
|
|
@@ -17599,15 +18938,17 @@ class PraxisDynamicForm {
|
|
|
17599
18938
|
return 'Erro';
|
|
17600
18939
|
if (this.aiAssistantViewState?.pendingPatch)
|
|
17601
18940
|
return 'Patch';
|
|
17602
|
-
return this.enableCustomization ? 'Form' : 'Ajuda';
|
|
18941
|
+
return this.enableCustomization ? 'Form' : (this.effectiveReadonly ? 'Ajuda' : 'Preencher');
|
|
17603
18942
|
}
|
|
17604
18943
|
resolveAiAssistantIcon() {
|
|
17605
18944
|
if (this.aiAssistantViewState?.state === 'error')
|
|
17606
18945
|
return 'error';
|
|
17607
18946
|
if (this.aiAssistantViewState?.state === 'review')
|
|
17608
18947
|
return 'rate_review';
|
|
17609
|
-
if (
|
|
18948
|
+
if (this.effectiveReadonly)
|
|
17610
18949
|
return 'help';
|
|
18950
|
+
if (!this.enableCustomization)
|
|
18951
|
+
return 'auto_awesome';
|
|
17611
18952
|
return 'dynamic_form';
|
|
17612
18953
|
}
|
|
17613
18954
|
resolveAiAssistantSelectedTarget() {
|
|
@@ -21635,6 +22976,15 @@ class PraxisDynamicForm {
|
|
|
21635
22976
|
this.tryInitializeForm();
|
|
21636
22977
|
}
|
|
21637
22978
|
getErrorTitle() {
|
|
22979
|
+
if (this.requiresConfirmedSchemaContext() && this.currentErrorDetails?.stage === 'schema-fetch') {
|
|
22980
|
+
return this.i18n.t('runtime.schemaRead.contextRequiredTitle', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
22981
|
+
}
|
|
22982
|
+
if ([401, 403].includes(Number(this.currentErrorDetails?.status))) {
|
|
22983
|
+
return this.i18n.t('runtime.schemaRead.deniedTitle', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
22984
|
+
}
|
|
22985
|
+
if (this.schemaValidationFailed && this.currentErrorDetails?.stage === 'schema-fetch') {
|
|
22986
|
+
return this.i18n.t('runtime.schemaRead.invalidTitle', undefined, undefined, PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE);
|
|
22987
|
+
}
|
|
21638
22988
|
const titles = {
|
|
21639
22989
|
'config-load': 'Configuração inválida',
|
|
21640
22990
|
'schema-fetch': 'Erro de conexão',
|
|
@@ -21671,9 +23021,7 @@ class PraxisDynamicForm {
|
|
|
21671
23021
|
const operation = (url.searchParams.get('operation') || 'get').toLowerCase();
|
|
21672
23022
|
const schemaType = (url.searchParams.get('schemaType') || 'response').toLowerCase();
|
|
21673
23023
|
const includeInternalSchemas = (url.searchParams.get('includeInternalSchemas') || 'false').toLowerCase() === 'true';
|
|
21674
|
-
const tenant
|
|
21675
|
-
const locale = url.searchParams.get('locale') ||
|
|
21676
|
-
((typeof navigator !== 'undefined' && navigator.language) ? navigator.language : undefined);
|
|
23024
|
+
const { tenant, locale } = this.schemaRepresentationContext(url.searchParams);
|
|
21677
23025
|
const origin = /^https?:\/\//i.test(resolvedSchemaUrl) ? url.origin : this.resolveApiOrigin();
|
|
21678
23026
|
const baseUrl = origin
|
|
21679
23027
|
? new URL(url.pathname, `${origin}/`).toString()
|
|
@@ -21720,10 +23068,28 @@ class PraxisDynamicForm {
|
|
|
21720
23068
|
}
|
|
21721
23069
|
catch { }
|
|
21722
23070
|
// Tenant/locale from GlobalConfigService and navigator
|
|
21723
|
-
const tenant = this.
|
|
21724
|
-
const locale = (typeof navigator !== 'undefined' && navigator.language) ? navigator.language : undefined;
|
|
23071
|
+
const { tenant, locale } = this.schemaRepresentationContext();
|
|
21725
23072
|
return { path, operation, schemaType, includeInternalSchemas: useFilterSchema, tenant, locale, baseUrl, apiOrigin };
|
|
21726
23073
|
}
|
|
23074
|
+
requiresConfirmedSchemaContext() {
|
|
23075
|
+
const snapshot = this.enterpriseRuntimeContext?.snapshot;
|
|
23076
|
+
return !!snapshot && snapshot.state !== 'ready';
|
|
23077
|
+
}
|
|
23078
|
+
schemaRepresentationContext(query) {
|
|
23079
|
+
if (this.requiresConfirmedSchemaContext())
|
|
23080
|
+
throw new Error('A confirmed runtime context is required to load the form schema.');
|
|
23081
|
+
const effective = this.enterpriseRuntimeContext?.effectiveContext;
|
|
23082
|
+
const requestedTenant = query?.get('tenant') || undefined;
|
|
23083
|
+
const requestedLocale = query?.get('locale') || undefined;
|
|
23084
|
+
if (effective && (requestedTenant && requestedTenant !== effective.activeTenant.tenantId ||
|
|
23085
|
+
requestedLocale && requestedLocale !== effective.locale))
|
|
23086
|
+
throw new Error('The schema URL conflicts with the confirmed runtime context.');
|
|
23087
|
+
return {
|
|
23088
|
+
tenant: effective ? effective.activeTenant.tenantId : requestedTenant || this.global?.getTenant?.(),
|
|
23089
|
+
locale: effective ? effective.locale ?? undefined : requestedLocale ||
|
|
23090
|
+
(typeof navigator !== 'undefined' ? navigator.language : undefined),
|
|
23091
|
+
};
|
|
23092
|
+
}
|
|
21727
23093
|
async getSchemaWithCache() {
|
|
21728
23094
|
const current = this.persistenceGuard(true);
|
|
21729
23095
|
const assertCurrent = () => {
|
|
@@ -21732,6 +23098,8 @@ class PraxisDynamicForm {
|
|
|
21732
23098
|
};
|
|
21733
23099
|
if (this.isDestroyed)
|
|
21734
23100
|
throw new PraxisDynamicFormDestroyedError();
|
|
23101
|
+
if (this.requiresConfirmedSchemaContext())
|
|
23102
|
+
throw new Error('A confirmed runtime context is required to load the form schema.');
|
|
21735
23103
|
if (this.schemaCache) {
|
|
21736
23104
|
this.debugLog('[PDF] schema:fromCache');
|
|
21737
23105
|
return this.schemaCache;
|
|
@@ -21739,6 +23107,7 @@ class PraxisDynamicForm {
|
|
|
21739
23107
|
const ctx = this.buildSchemaContext();
|
|
21740
23108
|
this.schemaRootReactiveDeterminations = [];
|
|
21741
23109
|
this.schemaRootOperationId = null;
|
|
23110
|
+
this.schemaRootHooks = undefined;
|
|
21742
23111
|
const schemaContext = {
|
|
21743
23112
|
path: ctx.path,
|
|
21744
23113
|
operation: ctx.operation,
|
|
@@ -21750,18 +23119,9 @@ class PraxisDynamicForm {
|
|
|
21750
23119
|
};
|
|
21751
23120
|
const disableCache = this.global.get('cache.disableSchemaCache');
|
|
21752
23121
|
const cacheKey = this.dynamicForm.buildSchemaCacheKey({ ...schemaContext, baseUrl: ctx.baseUrl });
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
this.debugLog('[PDF] schema:fromL1Cache', { cacheKey });
|
|
21757
|
-
this.schemaCache = compiled.normalizedFields;
|
|
21758
|
-
this.schemaRootOperationId = compiled.schemaRootOperationId ?? null;
|
|
21759
|
-
this.schemaRootHooks = compiled.schemaRootHooks;
|
|
21760
|
-
this.schemaRootReactiveDeterminations = compiled.schemaRootReactiveDeterminations ?? [];
|
|
21761
|
-
this.lastSchemaMeta = { schemaId: compiled.schemaId, serverHash: compiled.serverHash, context: schemaContext };
|
|
21762
|
-
return compiled.normalizedFields;
|
|
21763
|
-
}
|
|
21764
|
-
}
|
|
23122
|
+
// Compiled L1 values cannot establish readiness. Revalidate the structural
|
|
23123
|
+
// representation and normalize it again before reconciling this lifecycle.
|
|
23124
|
+
this.schemaValidationFailed = false;
|
|
21765
23125
|
const loadingCtx = this.buildLoadingContext('schema', 'Carregando configuração...', true);
|
|
21766
23126
|
this.beginLoading(loadingCtx);
|
|
21767
23127
|
this.emitLoadingState('schema', 'loading', 'Carregando schema do formulário...');
|
|
@@ -21784,6 +23144,8 @@ class PraxisDynamicForm {
|
|
|
21784
23144
|
: new LocalStorageCacheAdapter({ ttlMs: 30 * 60 * 1000, maxEntries: 200 });
|
|
21785
23145
|
const client = new SchemaMetadataClient(adapter, this.schemaTransportOptions);
|
|
21786
23146
|
let discoveryAttempted = false;
|
|
23147
|
+
let legacyAttempted = false;
|
|
23148
|
+
let representationReceived = false;
|
|
21787
23149
|
const loadDiscoverySchema = async (reason) => {
|
|
21788
23150
|
discoveryAttempted = true;
|
|
21789
23151
|
if (this.isDestroyed)
|
|
@@ -21794,7 +23156,9 @@ class PraxisDynamicForm {
|
|
|
21794
23156
|
...(this.apiUrlEntry ? { apiUrlEntry: this.apiUrlEntry } : {}),
|
|
21795
23157
|
};
|
|
21796
23158
|
const canLoadViaDiscovery = !!rp &&
|
|
21797
|
-
|
|
23159
|
+
(ctx.schemaType === 'request'
|
|
23160
|
+
? typeof this.resourceDiscovery?.getResourceFilterSchemaFields === 'function'
|
|
23161
|
+
: typeof this.resourceDiscovery?.getResourceSchemaFields === 'function') &&
|
|
21798
23162
|
(typeof this.resourceDiscovery.canResolveSchemas !== 'function' ||
|
|
21799
23163
|
this.resourceDiscovery.canResolveSchemas(discoveryOptions));
|
|
21800
23164
|
if (!canLoadViaDiscovery) {
|
|
@@ -21802,8 +23166,7 @@ class PraxisDynamicForm {
|
|
|
21802
23166
|
? reason
|
|
21803
23167
|
: new Error('Schema metadata unavailable and legacy crud.getSchema() not found.');
|
|
21804
23168
|
}
|
|
21805
|
-
const
|
|
21806
|
-
const useFilterSchema = this.schemaSource === 'filter' || inferredFilter;
|
|
23169
|
+
const useFilterSchema = ctx.schemaType === 'request';
|
|
21807
23170
|
const hasDedicatedOptions = !!(discoveryOptions.endpointKey || discoveryOptions.apiUrlEntry);
|
|
21808
23171
|
const discoveryCall$ = useFilterSchema && typeof this.resourceDiscovery.getResourceFilterSchemaFields === 'function'
|
|
21809
23172
|
? (hasDedicatedOptions
|
|
@@ -21828,11 +23191,8 @@ class PraxisDynamicForm {
|
|
|
21828
23191
|
assertCurrent();
|
|
21829
23192
|
if (this.isDestroyed)
|
|
21830
23193
|
throw new PraxisDynamicFormDestroyedError();
|
|
21831
|
-
if (!Array.isArray(discoveryDefs)
|
|
21832
|
-
throw
|
|
21833
|
-
? reason
|
|
21834
|
-
: new Error('Schema metadata unavailable via ResourceDiscoveryService.');
|
|
21835
|
-
}
|
|
23194
|
+
if (!Array.isArray(discoveryDefs))
|
|
23195
|
+
throw new Error('Invalid discovery schema field metadata.');
|
|
21836
23196
|
try {
|
|
21837
23197
|
const schemaId = buildSchemaId(schemaContext);
|
|
21838
23198
|
this.lastSchemaMeta = { schemaId, context: schemaContext };
|
|
@@ -21843,13 +23203,16 @@ class PraxisDynamicForm {
|
|
|
21843
23203
|
return discoveryDefs;
|
|
21844
23204
|
};
|
|
21845
23205
|
const loadLegacySchema = async (reason) => {
|
|
23206
|
+
legacyAttempted = true;
|
|
21846
23207
|
if (this.isDestroyed)
|
|
21847
23208
|
throw new PraxisDynamicFormDestroyedError();
|
|
21848
23209
|
try {
|
|
21849
23210
|
this.warnLog('[PDF] schema:metadata-fallback', reason);
|
|
21850
23211
|
}
|
|
21851
23212
|
catch { }
|
|
21852
|
-
const legacyGetSchema =
|
|
23213
|
+
const legacyGetSchema = ctx.schemaType === 'request'
|
|
23214
|
+
? this.crud?.getFilterSchema
|
|
23215
|
+
: this.crud?.getSchema;
|
|
21853
23216
|
if (typeof legacyGetSchema !== 'function') {
|
|
21854
23217
|
if (discoveryAttempted) {
|
|
21855
23218
|
throw reason instanceof Error
|
|
@@ -21861,7 +23224,9 @@ class PraxisDynamicForm {
|
|
|
21861
23224
|
const isMockedLegacy = !!legacyGetSchema?.and;
|
|
21862
23225
|
let legacyDefs;
|
|
21863
23226
|
try {
|
|
21864
|
-
const legacyResult =
|
|
23227
|
+
const legacyResult = ctx.schemaType === 'request'
|
|
23228
|
+
? legacyGetSchema.call(this.crud, { cache: false })
|
|
23229
|
+
: legacyGetSchema.call(this.crud);
|
|
21865
23230
|
controller.signal.throwIfAborted();
|
|
21866
23231
|
assertCurrent();
|
|
21867
23232
|
const cancelled$ = new Observable(subscriber => {
|
|
@@ -21882,7 +23247,8 @@ class PraxisDynamicForm {
|
|
|
21882
23247
|
if (this.isSchemaTransportInterruption(legacyError) ||
|
|
21883
23248
|
controller.signal.aborted ||
|
|
21884
23249
|
isMockedLegacy ||
|
|
21885
|
-
discoveryAttempted
|
|
23250
|
+
discoveryAttempted ||
|
|
23251
|
+
![404, 405, 501].includes(Number(legacyError?.status))) {
|
|
21886
23252
|
throw legacyError;
|
|
21887
23253
|
}
|
|
21888
23254
|
return await loadDiscoverySchema(legacyError);
|
|
@@ -21891,21 +23257,8 @@ class PraxisDynamicForm {
|
|
|
21891
23257
|
assertCurrent();
|
|
21892
23258
|
if (this.isDestroyed)
|
|
21893
23259
|
throw new PraxisDynamicFormDestroyedError();
|
|
21894
|
-
if (!
|
|
21895
|
-
|
|
21896
|
-
(!Array.isArray(legacyDefs) || legacyDefs.length === 0)) {
|
|
21897
|
-
try {
|
|
21898
|
-
return await loadDiscoverySchema(reason);
|
|
21899
|
-
}
|
|
21900
|
-
catch (discoveryError) {
|
|
21901
|
-
if (this.isDestroyed || discoveryError instanceof PraxisDynamicFormDestroyedError) {
|
|
21902
|
-
throw new PraxisDynamicFormDestroyedError();
|
|
21903
|
-
}
|
|
21904
|
-
if (this.isSchemaTransportInterruption(discoveryError) || controller.signal.aborted) {
|
|
21905
|
-
throw discoveryError;
|
|
21906
|
-
}
|
|
21907
|
-
}
|
|
21908
|
-
}
|
|
23260
|
+
if (!Array.isArray(legacyDefs))
|
|
23261
|
+
throw new Error('Invalid resource schema field metadata.');
|
|
21909
23262
|
try {
|
|
21910
23263
|
const schemaId = buildSchemaId(schemaContext);
|
|
21911
23264
|
this.lastSchemaMeta = { schemaId, context: schemaContext };
|
|
@@ -21917,7 +23270,8 @@ class PraxisDynamicForm {
|
|
|
21917
23270
|
};
|
|
21918
23271
|
try {
|
|
21919
23272
|
const legacyGetSchema = this.crud?.getSchema;
|
|
21920
|
-
const preferLegacySchema =
|
|
23273
|
+
const preferLegacySchema = !String(this.schemaUrl || '').trim() && ctx.schemaType === 'response' &&
|
|
23274
|
+
typeof legacyGetSchema === 'function' &&
|
|
21921
23275
|
!!legacyGetSchema?.and;
|
|
21922
23276
|
if (preferLegacySchema) {
|
|
21923
23277
|
return await loadLegacySchema(new Error('Using legacy schema source (mocked crud.getSchema).'));
|
|
@@ -21947,11 +23301,18 @@ class PraxisDynamicForm {
|
|
|
21947
23301
|
assertCurrent();
|
|
21948
23302
|
if (this.isDestroyed)
|
|
21949
23303
|
throw new PraxisDynamicFormDestroyedError();
|
|
21950
|
-
|
|
21951
|
-
|
|
21952
|
-
|
|
21953
|
-
|
|
21954
|
-
|
|
23304
|
+
representationReceived = true;
|
|
23305
|
+
let defs;
|
|
23306
|
+
try {
|
|
23307
|
+
if (!entry.schema || typeof entry.schema !== 'object' || Array.isArray(entry.schema) ||
|
|
23308
|
+
('properties' in entry.schema && (!entry.schema.properties || typeof entry.schema.properties !== 'object' || Array.isArray(entry.schema.properties)))) {
|
|
23309
|
+
throw new Error('Invalid structural schema representation.');
|
|
23310
|
+
}
|
|
23311
|
+
defs = this.schemaNormalizer.normalizeSchema(entry.schema);
|
|
23312
|
+
}
|
|
23313
|
+
catch (error) {
|
|
23314
|
+
this.schemaValidationFailed = true;
|
|
23315
|
+
throw error;
|
|
21955
23316
|
}
|
|
21956
23317
|
// Parse backend-owned root x-ui runtime contracts. They remain transient
|
|
21957
23318
|
// and are never copied into the persisted/authorable FormConfig.
|
|
@@ -22027,9 +23388,21 @@ class PraxisDynamicForm {
|
|
|
22027
23388
|
if (this.isSchemaTransportInterruption(error) || controller.signal.aborted)
|
|
22028
23389
|
throw error;
|
|
22029
23390
|
if (error instanceof InvalidReactiveDeterminationProjectionError) {
|
|
23391
|
+
this.schemaValidationFailed = true;
|
|
22030
23392
|
throw error;
|
|
22031
23393
|
}
|
|
22032
|
-
|
|
23394
|
+
const status = Number(error?.status);
|
|
23395
|
+
if (!representationReceived && !legacyAttempted && !discoveryAttempted &&
|
|
23396
|
+
!String(this.schemaUrl || '').trim() && ctx.schemaType === 'response' && [404, 405, 501].includes(status)) {
|
|
23397
|
+
return await loadLegacySchema(error);
|
|
23398
|
+
}
|
|
23399
|
+
if (error instanceof SyntaxError || error?.cause instanceof SyntaxError) {
|
|
23400
|
+
this.schemaValidationFailed = true;
|
|
23401
|
+
}
|
|
23402
|
+
if ((discoveryAttempted || legacyAttempted) && error instanceof Error &&
|
|
23403
|
+
!('status' in error) && error.name !== 'TypeError')
|
|
23404
|
+
this.schemaValidationFailed = true;
|
|
23405
|
+
throw error;
|
|
22033
23406
|
}
|
|
22034
23407
|
}
|
|
22035
23408
|
finally {
|
|
@@ -22185,12 +23558,418 @@ class PraxisDynamicForm {
|
|
|
22185
23558
|
this.effectiveConfig = normalizeFormConfig$1(this.config);
|
|
22186
23559
|
}
|
|
22187
23560
|
}
|
|
23561
|
+
getRuntimeValueTargetIdentity() {
|
|
23562
|
+
this.ensureRuntimeValueTracking();
|
|
23563
|
+
const rawId = this.resourceId ?? this.pendingEntityId ?? null;
|
|
23564
|
+
const entityId = typeof rawId === 'number' && Number.isFinite(rawId)
|
|
23565
|
+
? rawId
|
|
23566
|
+
: typeof rawId === 'string' && rawId.trim().length > 0
|
|
23567
|
+
? rawId.trim()
|
|
23568
|
+
: null;
|
|
23569
|
+
const schemaHash = this.lastSchemaMeta?.serverHash?.trim() ||
|
|
23570
|
+
this.schemaState.meta?.serverHash?.trim() ||
|
|
23571
|
+
this.config?.metadata?.['serverHash']
|
|
23572
|
+
?.toString()
|
|
23573
|
+
.trim() ||
|
|
23574
|
+
null;
|
|
23575
|
+
const normalizedMode = this.effectiveReadonly || this.effectivePresentation
|
|
23576
|
+
? 'view'
|
|
23577
|
+
: this.mode === 'edit'
|
|
23578
|
+
? 'edit'
|
|
23579
|
+
: this.mode === 'create'
|
|
23580
|
+
? 'create'
|
|
23581
|
+
: 'view';
|
|
23582
|
+
return {
|
|
23583
|
+
componentId: this.formId || this.componentInstanceId || 'praxis-dynamic-form',
|
|
23584
|
+
instanceId: this.componentInstanceId || this.formId || 'praxis-dynamic-form',
|
|
23585
|
+
formId: this.formId || null,
|
|
23586
|
+
resourcePath: this.resourcePath || null,
|
|
23587
|
+
mode: normalizedMode,
|
|
23588
|
+
entityId,
|
|
23589
|
+
schemaHash: schemaHash || null,
|
|
23590
|
+
valueRevision: this.runtimeValueRevision,
|
|
23591
|
+
};
|
|
23592
|
+
}
|
|
23593
|
+
getRuntimeValueEligibility() {
|
|
23594
|
+
this.ensureRuntimeValueTracking();
|
|
23595
|
+
const hasPendingReactiveDeterminations = this.reactiveDeterminationPending ||
|
|
23596
|
+
(this.form ? this.reactiveDeterminationRuntime.hasPending(this.form) : false);
|
|
23597
|
+
const hasPendingAsyncValidators = Boolean(this.form?.pending);
|
|
23598
|
+
const { writableFields, nonOverwritableFields } = this.collectRuntimeValueFieldClassification();
|
|
23599
|
+
if (this.effectiveReadonly ||
|
|
23600
|
+
this.effectivePresentation ||
|
|
23601
|
+
this.mode === 'view' ||
|
|
23602
|
+
this.mode === 'presentation' ||
|
|
23603
|
+
this.mode === 'dossier') {
|
|
23604
|
+
return {
|
|
23605
|
+
eligible: false,
|
|
23606
|
+
blockReason: 'view-mode-read-only',
|
|
23607
|
+
blockMessage: 'O formulário está em modo somente leitura e não aceita preenchimento.',
|
|
23608
|
+
autoSaveEnabled: false,
|
|
23609
|
+
hasPendingReactiveDeterminations,
|
|
23610
|
+
hasPendingAsyncValidators,
|
|
23611
|
+
writableFields: [],
|
|
23612
|
+
nonOverwritableFields,
|
|
23613
|
+
};
|
|
23614
|
+
}
|
|
23615
|
+
if (this.isLoading ||
|
|
23616
|
+
this.entityHydrationPending ||
|
|
23617
|
+
this.entityReadFailed ||
|
|
23618
|
+
this.initializationStatus === 'error') {
|
|
23619
|
+
return {
|
|
23620
|
+
eligible: false,
|
|
23621
|
+
blockReason: 'no-writable-fields',
|
|
23622
|
+
blockMessage: 'O formulário ainda não está pronto para preenchimento assistido.',
|
|
23623
|
+
autoSaveEnabled: false,
|
|
23624
|
+
hasPendingReactiveDeterminations,
|
|
23625
|
+
hasPendingAsyncValidators,
|
|
23626
|
+
writableFields: [],
|
|
23627
|
+
nonOverwritableFields,
|
|
23628
|
+
};
|
|
23629
|
+
}
|
|
23630
|
+
if (hasPendingReactiveDeterminations) {
|
|
23631
|
+
return {
|
|
23632
|
+
eligible: false,
|
|
23633
|
+
blockReason: 'pending-reactive-determinations',
|
|
23634
|
+
blockMessage: 'Existem determinações reativas em andamento. Aguarde a estabilização do formulário antes de aplicar valores.',
|
|
23635
|
+
autoSaveEnabled: false,
|
|
23636
|
+
hasPendingReactiveDeterminations,
|
|
23637
|
+
hasPendingAsyncValidators,
|
|
23638
|
+
writableFields,
|
|
23639
|
+
nonOverwritableFields,
|
|
23640
|
+
};
|
|
23641
|
+
}
|
|
23642
|
+
if (hasPendingAsyncValidators) {
|
|
23643
|
+
return {
|
|
23644
|
+
eligible: false,
|
|
23645
|
+
blockReason: 'pending-async-validators',
|
|
23646
|
+
blockMessage: 'Existem validações assíncronas pendentes no formulário. Aguarde a conclusão antes de aplicar valores.',
|
|
23647
|
+
autoSaveEnabled: false,
|
|
23648
|
+
hasPendingReactiveDeterminations,
|
|
23649
|
+
hasPendingAsyncValidators,
|
|
23650
|
+
writableFields,
|
|
23651
|
+
nonOverwritableFields,
|
|
23652
|
+
};
|
|
23653
|
+
}
|
|
23654
|
+
if (writableFields.length === 0) {
|
|
23655
|
+
return {
|
|
23656
|
+
eligible: false,
|
|
23657
|
+
blockReason: 'no-writable-fields',
|
|
23658
|
+
blockMessage: 'O formulário não possui campos elegíveis para preenchimento assistido.',
|
|
23659
|
+
autoSaveEnabled: false,
|
|
23660
|
+
hasPendingReactiveDeterminations,
|
|
23661
|
+
hasPendingAsyncValidators,
|
|
23662
|
+
writableFields,
|
|
23663
|
+
nonOverwritableFields,
|
|
23664
|
+
};
|
|
23665
|
+
}
|
|
23666
|
+
return {
|
|
23667
|
+
eligible: true,
|
|
23668
|
+
blockReason: null,
|
|
23669
|
+
blockMessage: null,
|
|
23670
|
+
autoSaveEnabled: false,
|
|
23671
|
+
hasPendingReactiveDeterminations,
|
|
23672
|
+
hasPendingAsyncValidators,
|
|
23673
|
+
writableFields,
|
|
23674
|
+
nonOverwritableFields,
|
|
23675
|
+
};
|
|
23676
|
+
}
|
|
23677
|
+
previewRuntimeValues(proposal, options) {
|
|
23678
|
+
this.ensureRuntimeValueTracking();
|
|
23679
|
+
return previewRuntimeFormValueProposal(this.createRuntimeFormHostCallbacks(), proposal, options);
|
|
23680
|
+
}
|
|
23681
|
+
applyRuntimeValues(request) {
|
|
23682
|
+
this.ensureRuntimeValueTracking();
|
|
23683
|
+
const receipt = applyRuntimeFormValueProposal(this.createRuntimeFormHostCallbacks(), this.runtimeValueJournal, request);
|
|
23684
|
+
if (receipt.appliedFields.length > 0) {
|
|
23685
|
+
this.cdr.markForCheck();
|
|
23686
|
+
}
|
|
23687
|
+
return receipt;
|
|
23688
|
+
}
|
|
23689
|
+
undoRuntimeValues(receiptId) {
|
|
23690
|
+
this.ensureRuntimeValueTracking();
|
|
23691
|
+
const receipt = undoRuntimeFormValueApply(this.createRuntimeFormHostCallbacks(), this.runtimeValueJournal, receiptId);
|
|
23692
|
+
if (receipt.revertedFields.length > 0) {
|
|
23693
|
+
this.cdr.markForCheck();
|
|
23694
|
+
}
|
|
23695
|
+
return receipt;
|
|
23696
|
+
}
|
|
23697
|
+
clearRuntimeValueControlSubscriptions() {
|
|
23698
|
+
for (const entry of this.runtimeValueTrackedControls.values()) {
|
|
23699
|
+
entry.sub.unsubscribe();
|
|
23700
|
+
}
|
|
23701
|
+
this.runtimeValueTrackedControls.clear();
|
|
23702
|
+
this.runtimeValueTrackedForm = null;
|
|
23703
|
+
}
|
|
23704
|
+
collectLeafFormControls(group, prefix = '', out = new Map()) {
|
|
23705
|
+
if (!group?.controls) {
|
|
23706
|
+
return out;
|
|
23707
|
+
}
|
|
23708
|
+
for (const [key, control] of Object.entries(group.controls)) {
|
|
23709
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
23710
|
+
if (control instanceof FormGroup) {
|
|
23711
|
+
this.collectLeafFormControls(control, path, out);
|
|
23712
|
+
}
|
|
23713
|
+
else if (control) {
|
|
23714
|
+
out.set(path, control);
|
|
23715
|
+
}
|
|
23716
|
+
}
|
|
23717
|
+
return out;
|
|
23718
|
+
}
|
|
23719
|
+
ensureRuntimeValueTracking() {
|
|
23720
|
+
if (!this.form) {
|
|
23721
|
+
return;
|
|
23722
|
+
}
|
|
23723
|
+
if (this.runtimeValueTrackedForm !== this.form) {
|
|
23724
|
+
this.clearRuntimeValueControlSubscriptions();
|
|
23725
|
+
this.runtimeValueTrackedForm = this.form;
|
|
23726
|
+
}
|
|
23727
|
+
const leafControls = this.collectLeafFormControls(this.form);
|
|
23728
|
+
for (const [fieldPath, control] of leafControls.entries()) {
|
|
23729
|
+
const existing = this.runtimeValueTrackedControls.get(fieldPath);
|
|
23730
|
+
if (existing?.control === control) {
|
|
23731
|
+
continue;
|
|
23732
|
+
}
|
|
23733
|
+
existing?.sub.unsubscribe();
|
|
23734
|
+
const sub = control.valueChanges
|
|
23735
|
+
.pipe(takeUntil(this.destroy$))
|
|
23736
|
+
.subscribe(() => {
|
|
23737
|
+
if (this.suppressCommandRuleSideEffectsDepth > 0 ||
|
|
23738
|
+
this.reactiveDeterminationRuntime.isOwnedTarget(this.form, control)) {
|
|
23739
|
+
return;
|
|
23740
|
+
}
|
|
23741
|
+
this.pendingSuppressedCommandEvaluation = false;
|
|
23742
|
+
this.runtimeValueRevision += 1;
|
|
23743
|
+
const instanceKey = instanceKeyFor(this.getRuntimeValueTargetIdentity());
|
|
23744
|
+
this.runtimeValueJournal.markFieldManuallyEdited(instanceKey, fieldPath);
|
|
23745
|
+
});
|
|
23746
|
+
this.runtimeValueTrackedControls.set(fieldPath, { control, sub });
|
|
23747
|
+
}
|
|
23748
|
+
}
|
|
23749
|
+
withSuppressedCommandSideEffects(fn) {
|
|
23750
|
+
this.suppressCommandRuleSideEffectsDepth += 1;
|
|
23751
|
+
this.pendingSuppressedCommandEvaluation = true;
|
|
23752
|
+
try {
|
|
23753
|
+
const result = fn();
|
|
23754
|
+
this.evaluateAndApplyRules();
|
|
23755
|
+
return result;
|
|
23756
|
+
}
|
|
23757
|
+
finally {
|
|
23758
|
+
this.suppressCommandRuleSideEffectsDepth = Math.max(0, this.suppressCommandRuleSideEffectsDepth - 1);
|
|
23759
|
+
}
|
|
23760
|
+
}
|
|
23761
|
+
createRuntimeFormHostCallbacks() {
|
|
23762
|
+
return {
|
|
23763
|
+
getTargetIdentity: () => this.getRuntimeValueTargetIdentity(),
|
|
23764
|
+
getEligibility: () => this.getRuntimeValueEligibility(),
|
|
23765
|
+
getControl: (fieldPath) => {
|
|
23766
|
+
const control = this.form?.get(fieldPath) ?? null;
|
|
23767
|
+
if (!control) {
|
|
23768
|
+
return null;
|
|
23769
|
+
}
|
|
23770
|
+
return {
|
|
23771
|
+
exists: true,
|
|
23772
|
+
getValue: () => control.value,
|
|
23773
|
+
setValue: (value) => {
|
|
23774
|
+
control.setValue(value);
|
|
23775
|
+
},
|
|
23776
|
+
isDirty: () => control.dirty,
|
|
23777
|
+
setDirty: (dirty) => {
|
|
23778
|
+
if (dirty) {
|
|
23779
|
+
control.markAsDirty();
|
|
23780
|
+
}
|
|
23781
|
+
else {
|
|
23782
|
+
control.markAsPristine({ onlySelf: true });
|
|
23783
|
+
const anyControlDirty = Object.values(this.form?.controls ?? {}).some((item) => item.dirty);
|
|
23784
|
+
if (!anyControlDirty) {
|
|
23785
|
+
this.form?.markAsPristine({ onlySelf: true });
|
|
23786
|
+
}
|
|
23787
|
+
}
|
|
23788
|
+
},
|
|
23789
|
+
isTouched: () => control.touched,
|
|
23790
|
+
setTouched: (touched) => {
|
|
23791
|
+
if (touched) {
|
|
23792
|
+
control.markAsTouched();
|
|
23793
|
+
}
|
|
23794
|
+
else {
|
|
23795
|
+
control.markAsUntouched({ onlySelf: true });
|
|
23796
|
+
const anyControlTouched = Object.values(this.form?.controls ?? {}).some((item) => item.touched);
|
|
23797
|
+
if (!anyControlTouched) {
|
|
23798
|
+
this.form?.markAsUntouched({ onlySelf: true });
|
|
23799
|
+
}
|
|
23800
|
+
}
|
|
23801
|
+
},
|
|
23802
|
+
};
|
|
23803
|
+
},
|
|
23804
|
+
incrementValueRevision: () => {
|
|
23805
|
+
this.runtimeValueRevision += 1;
|
|
23806
|
+
return this.runtimeValueRevision;
|
|
23807
|
+
},
|
|
23808
|
+
withSuppressedCommandSideEffects: (fn) => this.withSuppressedCommandSideEffects(fn),
|
|
23809
|
+
};
|
|
23810
|
+
}
|
|
23811
|
+
isConfiguredReactiveDeterminationOutputField(fieldPath) {
|
|
23812
|
+
const normalizedField = fieldPath.replace(/^\/+/, '');
|
|
23813
|
+
return (this.schemaRootReactiveDeterminations ?? []).some((definition) => (definition.outputs ?? []).some((binding) => binding.fieldPath.replace(/^\/+/, '') === normalizedField));
|
|
23814
|
+
}
|
|
23815
|
+
collectRuntimeValueFieldClassification() {
|
|
23816
|
+
const writableFields = [];
|
|
23817
|
+
const nonOverwritableFields = [];
|
|
23818
|
+
const metadataList = this.getRuntimeFieldMetadata();
|
|
23819
|
+
const metadataByName = new Map();
|
|
23820
|
+
for (const field of metadataList) {
|
|
23821
|
+
if (field?.name) {
|
|
23822
|
+
metadataByName.set(field.name, field);
|
|
23823
|
+
}
|
|
23824
|
+
}
|
|
23825
|
+
const leafControls = this.collectLeafFormControls(this.form);
|
|
23826
|
+
const allFieldNames = new Set([
|
|
23827
|
+
...metadataByName.keys(),
|
|
23828
|
+
...leafControls.keys(),
|
|
23829
|
+
]);
|
|
23830
|
+
const evalMode = this.mode === 'edit' ? 'edit' : this.mode === 'create' ? 'create' : 'view';
|
|
23831
|
+
for (const fieldPath of allFieldNames) {
|
|
23832
|
+
const field = metadataByName.get(fieldPath);
|
|
23833
|
+
const control = this.form?.get(fieldPath) ?? null;
|
|
23834
|
+
const label = typeof field?.['label'] === 'string' && field['label'].trim()
|
|
23835
|
+
? field['label'].trim()
|
|
23836
|
+
: fieldPath;
|
|
23837
|
+
const ruleProps = this.fieldRuleProps[fieldPath] ?? {};
|
|
23838
|
+
const xUi = (field?.['x-ui'] ?? {});
|
|
23839
|
+
const rawFieldAccess = field?.['fieldAccess'] ?? xUi['fieldAccess'];
|
|
23840
|
+
const access = evaluateFieldAccess(rawFieldAccess);
|
|
23841
|
+
const isDeterminationTarget = (control
|
|
23842
|
+
? this.reactiveDeterminationRuntime.isOwnedTarget(this.form, control)
|
|
23843
|
+
: false) || this.isConfiguredReactiveDeterminationOutputField(fieldPath);
|
|
23844
|
+
if (isDeterminationTarget) {
|
|
23845
|
+
nonOverwritableFields.push({
|
|
23846
|
+
fieldPath,
|
|
23847
|
+
label,
|
|
23848
|
+
reason: 'reactive-determination-target',
|
|
23849
|
+
message: 'Campo calculado por determinação reativa (ReactiveDetermination) não pode ser sobrescrito diretamente.',
|
|
23850
|
+
});
|
|
23851
|
+
continue;
|
|
23852
|
+
}
|
|
23853
|
+
const rawAiPolicy = String(field?.['aiUsagePolicy'] ??
|
|
23854
|
+
field?.['domainGovernance']?.['aiUsagePolicy'] ??
|
|
23855
|
+
xUi['aiUsagePolicy'] ??
|
|
23856
|
+
xUi['domainGovernance']?.['aiUsagePolicy'] ??
|
|
23857
|
+
rawFieldAccess?.['aiUsagePolicy'] ??
|
|
23858
|
+
'')
|
|
23859
|
+
.trim()
|
|
23860
|
+
.toUpperCase();
|
|
23861
|
+
const aiDisallowed = field?.['allowedForAiPrompting'] === false ||
|
|
23862
|
+
field?.['domainGovernance']?.['allowedForAiPrompting'] === false ||
|
|
23863
|
+
xUi['allowedForAiPrompting'] === false ||
|
|
23864
|
+
rawFieldAccess?.['allowedForAiPrompting'] === false ||
|
|
23865
|
+
rawAiPolicy === 'NEVER' ||
|
|
23866
|
+
rawAiPolicy === 'NONE' ||
|
|
23867
|
+
rawAiPolicy === 'FORBIDDEN' ||
|
|
23868
|
+
rawAiPolicy === 'READ_ONLY' ||
|
|
23869
|
+
rawAiPolicy === 'MASKED_ONLY' ||
|
|
23870
|
+
rawAiPolicy === 'REDACTED_ONLY';
|
|
23871
|
+
if (aiDisallowed) {
|
|
23872
|
+
nonOverwritableFields.push({
|
|
23873
|
+
fieldPath,
|
|
23874
|
+
label,
|
|
23875
|
+
reason: 'restricted-by-ai-policy',
|
|
23876
|
+
message: 'Campo restrito pela governança de IA (@DomainGovernance / AiUsagePolicy).',
|
|
23877
|
+
});
|
|
23878
|
+
continue;
|
|
23879
|
+
}
|
|
23880
|
+
const restrictedByFieldAccess = rawFieldAccess != null &&
|
|
23881
|
+
(access.editable === false ||
|
|
23882
|
+
access.visible === false ||
|
|
23883
|
+
(rawFieldAccess['creatable'] === false && evalMode === 'create') ||
|
|
23884
|
+
(rawFieldAccess['updatable'] === false && evalMode === 'edit') ||
|
|
23885
|
+
rawFieldAccess['writable'] === false);
|
|
23886
|
+
if (restrictedByFieldAccess) {
|
|
23887
|
+
nonOverwritableFields.push({
|
|
23888
|
+
fieldPath,
|
|
23889
|
+
label,
|
|
23890
|
+
reason: 'restricted-by-field-access',
|
|
23891
|
+
message: 'Campo restrito pela política de acesso (x-ui.fieldAccess).',
|
|
23892
|
+
});
|
|
23893
|
+
continue;
|
|
23894
|
+
}
|
|
23895
|
+
const isReadOnly = this.effectiveReadonly ||
|
|
23896
|
+
field?.['readOnly'] === true ||
|
|
23897
|
+
field?.['readonly'] === true ||
|
|
23898
|
+
xUi['readOnly'] === true ||
|
|
23899
|
+
xUi['readonly'] === true ||
|
|
23900
|
+
ruleProps['readOnly'] === true ||
|
|
23901
|
+
ruleProps['readonly'] === true;
|
|
23902
|
+
if (isReadOnly) {
|
|
23903
|
+
nonOverwritableFields.push({
|
|
23904
|
+
fieldPath,
|
|
23905
|
+
label,
|
|
23906
|
+
reason: 'read-only',
|
|
23907
|
+
message: 'Campo somente leitura não pode ser sobrescrito.',
|
|
23908
|
+
});
|
|
23909
|
+
continue;
|
|
23910
|
+
}
|
|
23911
|
+
const isDisabled = this.effectiveDisabledMode === true ||
|
|
23912
|
+
Boolean(control?.disabled) ||
|
|
23913
|
+
field?.['disabled'] === true ||
|
|
23914
|
+
xUi['disabled'] === true ||
|
|
23915
|
+
ruleProps['disabled'] === true;
|
|
23916
|
+
if (isDisabled) {
|
|
23917
|
+
nonOverwritableFields.push({
|
|
23918
|
+
fieldPath,
|
|
23919
|
+
label,
|
|
23920
|
+
reason: 'disabled',
|
|
23921
|
+
message: 'Campo desabilitado não pode ser sobrescrito.',
|
|
23922
|
+
});
|
|
23923
|
+
continue;
|
|
23924
|
+
}
|
|
23925
|
+
const isHidden = this.fieldVisibility[fieldPath] === false ||
|
|
23926
|
+
ruleProps['hidden'] === true ||
|
|
23927
|
+
ruleProps['visible'] === false ||
|
|
23928
|
+
field?.['hidden'] === true ||
|
|
23929
|
+
field?.['visible'] === false ||
|
|
23930
|
+
xUi['hidden'] === true ||
|
|
23931
|
+
xUi['visible'] === false;
|
|
23932
|
+
if (isHidden) {
|
|
23933
|
+
nonOverwritableFields.push({
|
|
23934
|
+
fieldPath,
|
|
23935
|
+
label,
|
|
23936
|
+
reason: 'hidden',
|
|
23937
|
+
message: 'Campo oculto não pode ser sobrescrito.',
|
|
23938
|
+
});
|
|
23939
|
+
continue;
|
|
23940
|
+
}
|
|
23941
|
+
if (!control) {
|
|
23942
|
+
nonOverwritableFields.push({
|
|
23943
|
+
fieldPath,
|
|
23944
|
+
label,
|
|
23945
|
+
reason: 'unsupported-control',
|
|
23946
|
+
message: 'Controle não encontrado no formulário ativo.',
|
|
23947
|
+
});
|
|
23948
|
+
continue;
|
|
23949
|
+
}
|
|
23950
|
+
const optionSource = (field?.['optionSource'] ??
|
|
23951
|
+
xUi['optionSource'] ??
|
|
23952
|
+
null);
|
|
23953
|
+
writableFields.push({
|
|
23954
|
+
fieldPath,
|
|
23955
|
+
label,
|
|
23956
|
+
dataType: field?.['type'] ??
|
|
23957
|
+
field?.['dataType'] ??
|
|
23958
|
+
null,
|
|
23959
|
+
controlType: field?.['controlType'] ?? null,
|
|
23960
|
+
required: Boolean(field?.['required']),
|
|
23961
|
+
optionSourceKey: typeof optionSource?.['key'] === 'string' ? optionSource['key'] : null,
|
|
23962
|
+
optionSourceType: typeof optionSource?.['type'] === 'string' ? optionSource['type'] : null,
|
|
23963
|
+
});
|
|
23964
|
+
}
|
|
23965
|
+
return { writableFields, nonOverwritableFields };
|
|
23966
|
+
}
|
|
22188
23967
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicForm, deps: [{ token: i1.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.DynamicFormService }, { token: i9.MatSnackBar }, { token: CanvasStateService }, { token: DynamicFormLayoutService }, { token: ReactiveDeterminationRuntimeService }, { token: i1.ErrorMessageService }, { token: i1.SchemaNormalizerService }, { token: i1.ComponentMetadataRegistry }, { token: i1.GlobalConfigService }, { token: i1.ComponentKeyService }, { token: i1.LoadingOrchestrator }, { token: i0.NgZone }, { token: API_URL }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i13.Router, optional: true }, { token: i13.ActivatedRoute, optional: true }, { token: i1.FormHooksRegistry, optional: true }, { token: FORM_HOOKS_PRESETS, optional: true }, { token: i1.LoggerService, optional: true }, { token: i1.EnterpriseRuntimeContextService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
22189
23968
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDynamicForm, isStandalone: true, selector: "praxis-dynamic-form", inputs: { resourcePath: "resourcePath", resourceId: "resourceId", initialValue: "initialValue", emptyState: "emptyState", editorialContext: "editorialContext", mode: "mode", config: "config", actions: "actions", schemaSource: "schemaSource", actionId: "actionId", operationId: "operationId", schemaUrl: "schemaUrl", readUrl: "readUrl", submitUrl: "submitUrl", submitMethod: "submitMethod", submitIdempotencyKey: "submitIdempotencyKey", submitCorrelationId: "submitCorrelationId", submitResourceVersion: "submitResourceVersion", submitResourceVersionTargetResourceKey: "submitResourceVersionTargetResourceKey", submitResourceVersionTargetIdField: "submitResourceVersionTargetIdField", responseSchemaUrl: "responseSchemaUrl", apiEndpointKey: "apiEndpointKey", apiUrlEntry: "apiUrlEntry", enableCustomization: "enableCustomization", showAiAssistant: "showAiAssistant", formId: "formId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", layout: "layout", layoutMode: "layoutMode", formLayout: "formLayout", generatedLayoutPreset: "generatedLayoutPreset", layoutPolicy: "layoutPolicy", backConfig: "backConfig", hooks: "hooks", removeEmptyContainersOnSave: "removeEmptyContainersOnSave", reactiveValidation: "reactiveValidation", reactiveValidationDebounceMs: "reactiveValidationDebounceMs", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", readonlyModeGlobal: "readonlyModeGlobal", disabledModeGlobal: "disabledModeGlobal", presentationModeGlobal: "presentationModeGlobal", presentation: "presentation", presentationPreset: "presentationPreset", sectionDefaultAppearance: "sectionDefaultAppearance", sectionDivider: "sectionDivider", visibleGlobal: "visibleGlobal", fieldIconPolicy: "fieldIconPolicy", domainRules: "domainRules", customEndpoints: "customEndpoints" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formReset: "formReset", configChange: "configChange", configPatchChange: "configPatchChange", formReady: "formReady", valueChange: "valueChange", payloadPreviewChange: "payloadPreviewChange", syncCompleted: "syncCompleted", initializationError: "initializationError", loadingStateChange: "loadingStateChange", enableCustomizationChange: "enableCustomizationChange", customAction: "customAction", actionConfirmation: "actionConfirmation", schemaStatusChange: "schemaStatusChange", fieldRenderError: "fieldRenderError", ruleDiagnosticsChange: "ruleDiagnosticsChange", reactiveDeterminationExecuted: "reactiveDeterminationExecuted", reactiveDeterminationPendingChange: "reactiveDeterminationPendingChange", tabChange: "tabChange", tabSelected: "tabSelected" }, providers: [
|
|
22190
23969
|
providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG),
|
|
22191
23970
|
GenericCrudService,
|
|
22192
23971
|
FormContextService,
|
|
22193
|
-
], 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\" aria-label=\"Carregando formul\u00E1rio\"></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 @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [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]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\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 @if (enableCustomization && selectedElement) {\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 [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\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 [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\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]=\"getEffectiveSectionTitleGapBottom(section)\" [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\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\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\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\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 [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\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 <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\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 </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\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, row)\"\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]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\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 (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\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 (isLastVisibleSection(section) && 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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\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}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--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 );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.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 button{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}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.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%,var(--md-sys-color-on-surface) 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;max-width:100%;min-width:0;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( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, 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( --pdx-color-primary, 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;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--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.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--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( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--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, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);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]{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{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.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.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.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}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.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:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.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:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.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}.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);max-width:100%;min-width:0;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=entityLookup],.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;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;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){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.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}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.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],[formArray],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", "canvasFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i17.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.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: i19.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { 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", "suppressInvalidSubmitHint", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
|
|
23972
|
+
], 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\" aria-label=\"Carregando formul\u00E1rio\"></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 @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [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]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\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 @if (enableCustomization && selectedElement) {\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 [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\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 [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\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]=\"getEffectiveSectionTitleGapBottom(section)\" [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\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\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\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\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 [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\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 <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\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 </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @if (sectionIndex === 0) {\n @let targetSummary = getActionTargetRecordSummary();\n @if (targetSummary) {\n <div class=\"form-action-target-banner\" data-testid=\"form-action-target-banner\">\n <div class=\"form-action-target-banner__header\">\n <span class=\"form-action-target-banner__eyebrow\">{{ actionTargetSelectedRecordLabel }}</span>\n @if (targetSummary.id) {\n <span class=\"form-action-target-banner__id\">#{{ targetSummary.id }}</span>\n }\n @if (targetSummary.badges.length) {\n <div class=\"form-action-target-banner__badges\">\n @for (badge of targetSummary.badges; track badge.label) {\n <span\n class=\"form-action-target-banner__badge\"\n [attr.data-tone]=\"badge.tone\"\n >{{ badge.value }}</span>\n }\n </div>\n }\n </div>\n @if (targetSummary.title) {\n <div class=\"form-action-target-banner__title\">{{ targetSummary.title }}</div>\n }\n @if (targetSummary.subtitle) {\n <div class=\"form-action-target-banner__subtitle\">{{ targetSummary.subtitle }}</div>\n }\n </div>\n }\n }\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, row)\"\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]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\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 (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\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 (isLastVisibleSection(section) && 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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n [attr.aria-label]=\"effectiveReadonly ? 'Pedir ajuda sobre este formul\u00E1rio' : 'Abrir assistente de preenchimento do formul\u00E1rio'\"\n [matTooltip]=\"effectiveReadonly ? 'Pedir ajuda sobre este formul\u00E1rio' : 'Assistente de preenchimento'\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [preview]=\"aiAssistantViewState.preview\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply($event)\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\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}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--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 );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.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 button{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}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.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%,var(--md-sys-color-on-surface) 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;max-width:100%;min-width:0;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( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, 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( --pdx-color-primary, 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;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--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.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--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( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--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, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);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]{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{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.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.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.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}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.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:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.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:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.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}.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);max-width:100%;min-width:0;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=entityLookup],.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;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;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){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.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}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}.form-action-target-banner{display:flex;flex-direction:column;gap:6px;margin-bottom:18px;padding:12px 14px;border-radius:8px;border-left:3px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,var(--md-sys-color-surface-container-low, var(--md-sys-color-surface)))}.form-action-target-banner__header{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.form-action-target-banner__eyebrow{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--md-sys-color-primary)}.form-action-target-banner__id{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;font-weight:600;padding:1px 6px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface-variant)}.form-action-target-banner__badges{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px;margin-left:auto}.form-action-target-banner__badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;font-size:.6875rem;font-weight:600;letter-spacing:.02em;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);color:var(--md-sys-color-on-surface)}.form-action-target-banner__badge[data-tone=info]{background:color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent);color:var(--md-sys-color-primary)}.form-action-target-banner__badge[data-tone=success]{background:#10b98129;color:#059669}.form-action-target-banner__badge[data-tone=warning]{background:#f59e0b2e;color:#d97706}.form-action-target-banner__badge[data-tone=danger]{background:color-mix(in srgb,var(--md-sys-color-error) 16%,transparent);color:var(--md-sys-color-error)}.form-action-target-banner__title{font-size:.95rem;font-weight:650;line-height:1.3;color:var(--md-sys-color-on-surface)}.form-action-target-banner__subtitle{font-size:.8125rem;line-height:1.4;color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.form-context-empty-state{min-height:320px;display:flex;align-items:center;justify-content:center;padding:24px 20px;border-radius:16px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant, #444746) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--md-sys-color-surface)) 72%,transparent);box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.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],[formArray],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", "canvasFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i17.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.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: i19.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { 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", "suppressInvalidSubmitHint", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "preview", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
|
|
22194
23973
|
}
|
|
22195
23974
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicForm, decorators: [{
|
|
22196
23975
|
type: Component,
|
|
@@ -22216,7 +23995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
22216
23995
|
EmptyStateCardComponent,
|
|
22217
23996
|
PraxisAiAssistantShellComponent,
|
|
22218
23997
|
PraxisRichContent,
|
|
22219
|
-
], 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\" aria-label=\"Carregando formul\u00E1rio\"></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 @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [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]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\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 @if (enableCustomization && selectedElement) {\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 [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\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 [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\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]=\"getEffectiveSectionTitleGapBottom(section)\" [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\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\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\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\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 [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\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 <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\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 </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\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, row)\"\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]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\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 (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\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 (isLastVisibleSection(section) && 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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\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}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--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 );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.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 button{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}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.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%,var(--md-sys-color-on-surface) 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;max-width:100%;min-width:0;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( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, 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( --pdx-color-primary, 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;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--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.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--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( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--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, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);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]{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{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.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.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.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}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.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:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.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:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.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}.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);max-width:100%;min-width:0;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=entityLookup],.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;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;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){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.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}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}\n"] }]
|
|
23998
|
+
], 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\" aria-label=\"Carregando formul\u00E1rio\"></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 @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [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]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\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 @if (enableCustomization && selectedElement) {\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 [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\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 [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\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]=\"getEffectiveSectionTitleGapBottom(section)\" [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\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\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\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\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 [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\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 <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\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 </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @if (sectionIndex === 0) {\n @let targetSummary = getActionTargetRecordSummary();\n @if (targetSummary) {\n <div class=\"form-action-target-banner\" data-testid=\"form-action-target-banner\">\n <div class=\"form-action-target-banner__header\">\n <span class=\"form-action-target-banner__eyebrow\">{{ actionTargetSelectedRecordLabel }}</span>\n @if (targetSummary.id) {\n <span class=\"form-action-target-banner__id\">#{{ targetSummary.id }}</span>\n }\n @if (targetSummary.badges.length) {\n <div class=\"form-action-target-banner__badges\">\n @for (badge of targetSummary.badges; track badge.label) {\n <span\n class=\"form-action-target-banner__badge\"\n [attr.data-tone]=\"badge.tone\"\n >{{ badge.value }}</span>\n }\n </div>\n }\n </div>\n @if (targetSummary.title) {\n <div class=\"form-action-target-banner__title\">{{ targetSummary.title }}</div>\n }\n @if (targetSummary.subtitle) {\n <div class=\"form-action-target-banner__subtitle\">{{ targetSummary.subtitle }}</div>\n }\n </div>\n }\n }\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, row)\"\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]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\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 (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\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 (isLastVisibleSection(section) && 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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></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 [hostCapabilities]=\"richContentHostCapabilities\"\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 [suppressInvalidSubmitHint]=\"entityHydrationPending\"\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 [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n [attr.aria-label]=\"effectiveReadonly ? 'Pedir ajuda sobre este formul\u00E1rio' : 'Abrir assistente de preenchimento do formul\u00E1rio'\"\n [matTooltip]=\"effectiveReadonly ? 'Pedir ajuda sobre este formul\u00E1rio' : 'Assistente de preenchimento'\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [preview]=\"aiAssistantViewState.preview\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply($event)\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\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}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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}}@container praxis-form-row (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;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--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 );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.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 button{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}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.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%,var(--md-sys-color-on-surface) 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;max-width:100%;min-width:0;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( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, 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( --pdx-color-primary, 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;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--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.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--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( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--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, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);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]{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{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.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.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.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}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.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:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.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:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.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}.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);max-width:100%;min-width:0;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=entityLookup],.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;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;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){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.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}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}.form-action-target-banner{display:flex;flex-direction:column;gap:6px;margin-bottom:18px;padding:12px 14px;border-radius:8px;border-left:3px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,var(--md-sys-color-surface-container-low, var(--md-sys-color-surface)))}.form-action-target-banner__header{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.form-action-target-banner__eyebrow{font-size:.6875rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--md-sys-color-primary)}.form-action-target-banner__id{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:.75rem;font-weight:600;padding:1px 6px;border-radius:4px;background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface-variant)}.form-action-target-banner__badges{display:inline-flex;flex-wrap:wrap;align-items:center;gap:6px;margin-left:auto}.form-action-target-banner__badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;font-size:.6875rem;font-weight:600;letter-spacing:.02em;background:color-mix(in srgb,var(--md-sys-color-on-surface) 10%,transparent);color:var(--md-sys-color-on-surface)}.form-action-target-banner__badge[data-tone=info]{background:color-mix(in srgb,var(--md-sys-color-primary) 16%,transparent);color:var(--md-sys-color-primary)}.form-action-target-banner__badge[data-tone=success]{background:#10b98129;color:#059669}.form-action-target-banner__badge[data-tone=warning]{background:#f59e0b2e;color:#d97706}.form-action-target-banner__badge[data-tone=danger]{background:color-mix(in srgb,var(--md-sys-color-error) 16%,transparent);color:var(--md-sys-color-error)}.form-action-target-banner__title{font-size:.95rem;font-weight:650;line-height:1.3;color:var(--md-sys-color-on-surface)}.form-action-target-banner__subtitle{font-size:.8125rem;line-height:1.4;color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.form-context-empty-state{min-height:320px;display:flex;align-items:center;justify-content:center;padding:24px 20px;border-radius:16px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant, #444746) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low, var(--md-sys-color-surface)) 72%,transparent);box-sizing:border-box}\n"] }]
|
|
22220
23999
|
}], ctorParameters: () => [{ type: i1.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: [{
|
|
22221
24000
|
type: Inject,
|
|
22222
24001
|
args: [ASYNC_CONFIG_STORAGE]
|
|
@@ -34250,9 +36029,9 @@ function stableStringify(value) {
|
|
|
34250
36029
|
}
|
|
34251
36030
|
|
|
34252
36031
|
var index = /*#__PURE__*/Object.freeze({
|
|
34253
|
-
|
|
34254
|
-
|
|
34255
|
-
|
|
36032
|
+
__proto__: null,
|
|
36033
|
+
PraxisDynamicFormConfigEditor: PraxisDynamicFormConfigEditor,
|
|
36034
|
+
stripLegacyFieldMetadata: stripLegacyFieldMetadata
|
|
34256
36035
|
});
|
|
34257
36036
|
|
|
34258
36037
|
class PraxisFilterForm {
|
|
@@ -34280,7 +36059,8 @@ class PraxisFilterForm {
|
|
|
34280
36059
|
statusChangesSub;
|
|
34281
36060
|
schemaSub;
|
|
34282
36061
|
hydratedFieldMetadata = [];
|
|
34283
|
-
|
|
36062
|
+
schemaHydrationPending = false;
|
|
36063
|
+
schemaHydrationFailed = false;
|
|
34284
36064
|
columnFieldsCache = new WeakMap();
|
|
34285
36065
|
singleFieldCache = new WeakMap();
|
|
34286
36066
|
crudService = (() => {
|
|
@@ -34315,7 +36095,8 @@ class PraxisFilterForm {
|
|
|
34315
36095
|
if (hasConfiguredFields) {
|
|
34316
36096
|
this.schemaSub?.unsubscribe();
|
|
34317
36097
|
this.hydratedFieldMetadata = [];
|
|
34318
|
-
this.
|
|
36098
|
+
this.schemaHydrationPending = false;
|
|
36099
|
+
this.schemaHydrationFailed = false;
|
|
34319
36100
|
}
|
|
34320
36101
|
if ('config' in changes && this.config?.fieldMetadata) {
|
|
34321
36102
|
this.buildForm();
|
|
@@ -34338,9 +36119,10 @@ class PraxisFilterForm {
|
|
|
34338
36119
|
(this.config?.resourcePath ?? '')).trim();
|
|
34339
36120
|
if (!rp) {
|
|
34340
36121
|
this.schemaSub?.unsubscribe();
|
|
36122
|
+
this.schemaHydrationPending = false;
|
|
36123
|
+
this.schemaHydrationFailed = false;
|
|
34341
36124
|
if (this.hydratedFieldMetadata.length > 0) {
|
|
34342
36125
|
this.hydratedFieldMetadata = [];
|
|
34343
|
-
this.lastHydratedResourceKey = '';
|
|
34344
36126
|
this.buildForm();
|
|
34345
36127
|
}
|
|
34346
36128
|
return;
|
|
@@ -34351,19 +36133,10 @@ class PraxisFilterForm {
|
|
|
34351
36133
|
...(this.apiUrlEntry ? { apiUrlEntry: this.apiUrlEntry } : {}),
|
|
34352
36134
|
}
|
|
34353
36135
|
: undefined;
|
|
34354
|
-
const hydrationKey = JSON.stringify({
|
|
34355
|
-
rp,
|
|
34356
|
-
endpointKey: this.endpointKey ?? null,
|
|
34357
|
-
apiUrlEntry: this.apiUrlEntry ?? null,
|
|
34358
|
-
});
|
|
34359
|
-
if (this.lastHydratedResourceKey === hydrationKey && this.hydratedFieldMetadata.length > 0) {
|
|
34360
|
-
return;
|
|
34361
|
-
}
|
|
34362
36136
|
const canLoadViaDiscovery = typeof this.resourceDiscovery?.getResourceFilterSchemaFields === 'function' &&
|
|
34363
36137
|
(typeof this.resourceDiscovery.canResolveSchemas !== 'function' ||
|
|
34364
36138
|
this.resourceDiscovery.canResolveSchemas(discoveryOptions));
|
|
34365
|
-
const canLoadViaCrud = typeof this.crudService?.getFilterSchema === 'function'
|
|
34366
|
-
typeof this.crudService?.getSchema === 'function';
|
|
36139
|
+
const canLoadViaCrud = typeof this.crudService?.getFilterSchema === 'function';
|
|
34367
36140
|
if (!canLoadViaCrud && !canLoadViaDiscovery) {
|
|
34368
36141
|
return;
|
|
34369
36142
|
}
|
|
@@ -34381,43 +36154,48 @@ class PraxisFilterForm {
|
|
|
34381
36154
|
this.crudService.configure?.(rp);
|
|
34382
36155
|
}
|
|
34383
36156
|
return typeof this.crudService.getFilterSchema === 'function'
|
|
34384
|
-
? this.crudService.getFilterSchema()
|
|
34385
|
-
:
|
|
36157
|
+
? this.crudService.getFilterSchema({ cache: false })
|
|
36158
|
+
: throwError(() => new Error('A request filter schema source is required.'));
|
|
34386
36159
|
};
|
|
34387
36160
|
const isCatalogResourceKey = !rp.includes('/') && rp.includes('.');
|
|
36161
|
+
const isUnavailable = (error) => !!error && typeof error === 'object' && 'status' in error &&
|
|
36162
|
+
[404, 405, 501].includes(Number(error.status));
|
|
34388
36163
|
let source$;
|
|
34389
36164
|
if (isCatalogResourceKey && canLoadViaDiscovery) {
|
|
34390
|
-
source$ = loadFromDiscovery
|
|
34391
|
-
? loadFromCrud()
|
|
34392
|
-
: of(defs)), catchError$1(() => (canLoadViaCrud ? loadFromCrud() : of([]))));
|
|
36165
|
+
source$ = defer(loadFromDiscovery).pipe(catchError$1(error => canLoadViaCrud && isUnavailable(error) ? defer(loadFromCrud) : throwError(() => error)));
|
|
34393
36166
|
}
|
|
34394
36167
|
else if (canLoadViaCrud) {
|
|
34395
|
-
source$ = loadFromCrud
|
|
34396
|
-
? loadFromDiscovery()
|
|
34397
|
-
: of(defs)), catchError$1(() => (canLoadViaDiscovery ? loadFromDiscovery() : of([]))));
|
|
36168
|
+
source$ = defer(loadFromCrud).pipe(catchError$1(error => canLoadViaDiscovery && isUnavailable(error) ? defer(loadFromDiscovery) : throwError(() => error)));
|
|
34398
36169
|
}
|
|
34399
36170
|
else {
|
|
34400
|
-
source$ = loadFromDiscovery
|
|
36171
|
+
source$ = defer(loadFromDiscovery);
|
|
34401
36172
|
}
|
|
34402
36173
|
this.schemaSub?.unsubscribe();
|
|
36174
|
+
this.schemaHydrationPending = true;
|
|
36175
|
+
this.schemaHydrationFailed = false;
|
|
36176
|
+
this.validityChange.emit(false);
|
|
34403
36177
|
this.schemaSub = source$
|
|
34404
|
-
.pipe(
|
|
34405
|
-
.subscribe((defs) => {
|
|
34406
|
-
|
|
34407
|
-
|
|
34408
|
-
|
|
34409
|
-
|
|
34410
|
-
|
|
34411
|
-
|
|
34412
|
-
|
|
34413
|
-
|
|
34414
|
-
|
|
34415
|
-
|
|
34416
|
-
|
|
34417
|
-
|
|
34418
|
-
|
|
34419
|
-
|
|
34420
|
-
|
|
36178
|
+
.pipe(defaultIfEmpty([]), take$1(1))
|
|
36179
|
+
.subscribe({ next: (defs) => {
|
|
36180
|
+
this.schemaHydrationPending = false;
|
|
36181
|
+
if (!Array.isArray(defs)) {
|
|
36182
|
+
this.schemaHydrationFailed = true;
|
|
36183
|
+
this.validityChange.emit(false);
|
|
36184
|
+
return;
|
|
36185
|
+
}
|
|
36186
|
+
if (Array.isArray(this.config?.fieldMetadata) && this.config.fieldMetadata.length > 0) {
|
|
36187
|
+
return;
|
|
36188
|
+
}
|
|
36189
|
+
const metadata = mapFieldDefinitionsToMetadata(defs);
|
|
36190
|
+
this.hydratedFieldMetadata = metadata;
|
|
36191
|
+
this.buildForm();
|
|
36192
|
+
this.cdr?.markForCheck();
|
|
36193
|
+
}, error: () => {
|
|
36194
|
+
this.schemaHydrationPending = false;
|
|
36195
|
+
this.schemaHydrationFailed = true;
|
|
36196
|
+
this.validityChange.emit(false);
|
|
36197
|
+
this.cdr?.markForCheck();
|
|
36198
|
+
} });
|
|
34421
36199
|
}
|
|
34422
36200
|
buildForm() {
|
|
34423
36201
|
this.valueChangesSub?.unsubscribe();
|
|
@@ -34431,34 +36209,85 @@ class PraxisFilterForm {
|
|
|
34431
36209
|
this.form.patchValue(this.buildRestorableValues(fields, previous));
|
|
34432
36210
|
this.formReady.emit({ formGroup: this.form });
|
|
34433
36211
|
// Emitir estado inicial de validade e assinar mudanças
|
|
34434
|
-
this.validityChange.emit(this.
|
|
36212
|
+
this.validityChange.emit(this.isFilterReady());
|
|
34435
36213
|
this.statusChangesSub = this.form.statusChanges.subscribe(() => {
|
|
34436
|
-
this.validityChange.emit(this.
|
|
36214
|
+
this.validityChange.emit(this.isFilterReady());
|
|
34437
36215
|
});
|
|
34438
36216
|
this.valueChangesSub = this.form.valueChanges.subscribe((val) => {
|
|
34439
|
-
this.
|
|
36217
|
+
if (!this.isFilterReady()) {
|
|
36218
|
+
this.validityChange.emit(false);
|
|
36219
|
+
return;
|
|
36220
|
+
}
|
|
36221
|
+
const formData = this.projectFilterValues(val || {});
|
|
36222
|
+
if (formData === null) {
|
|
36223
|
+
this.validityChange.emit(false);
|
|
36224
|
+
return;
|
|
36225
|
+
}
|
|
36226
|
+
this.valueChange.emit({ formData });
|
|
34440
36227
|
});
|
|
34441
36228
|
}
|
|
34442
36229
|
buildRestorableValues(fields, previous) {
|
|
34443
36230
|
return fields.reduce((acc, field) => {
|
|
34444
|
-
if (!this.form.
|
|
36231
|
+
if (!this.form.get(field.name)) {
|
|
34445
36232
|
return acc;
|
|
34446
36233
|
}
|
|
34447
36234
|
if (this.hasExplicitDefaultValue(field)) {
|
|
34448
36235
|
return acc;
|
|
34449
36236
|
}
|
|
34450
|
-
if (!(field.name
|
|
36237
|
+
if (!hasNestedPath(previous, field.name)) {
|
|
34451
36238
|
return acc;
|
|
34452
36239
|
}
|
|
34453
|
-
|
|
34454
|
-
|
|
36240
|
+
const value = getNestedPath(previous, field.name);
|
|
36241
|
+
if (!field.name.includes('.')) {
|
|
36242
|
+
acc[field.name] = value;
|
|
36243
|
+
return acc;
|
|
36244
|
+
}
|
|
36245
|
+
return setNestedPath(acc, field.name, value);
|
|
34455
36246
|
}, {});
|
|
34456
36247
|
}
|
|
34457
36248
|
hasExplicitDefaultValue(field) {
|
|
34458
36249
|
return Object.prototype.hasOwnProperty.call(field, 'defaultValue');
|
|
34459
36250
|
}
|
|
34460
36251
|
onFormSubmit() {
|
|
34461
|
-
this.
|
|
36252
|
+
if (this.schemaHydrationPending || this.schemaHydrationFailed)
|
|
36253
|
+
return;
|
|
36254
|
+
if (this.form.invalid || this.form.pending) {
|
|
36255
|
+
this.form.markAllAsTouched();
|
|
36256
|
+
return;
|
|
36257
|
+
}
|
|
36258
|
+
const formData = this.projectFilterValues(this.form.getRawValue());
|
|
36259
|
+
if (formData === null) {
|
|
36260
|
+
this.validityChange.emit(false);
|
|
36261
|
+
this.form.markAllAsTouched();
|
|
36262
|
+
return;
|
|
36263
|
+
}
|
|
36264
|
+
this.submit.emit({ formData });
|
|
36265
|
+
}
|
|
36266
|
+
isFilterReady() {
|
|
36267
|
+
return !this.schemaHydrationPending && !this.schemaHydrationFailed &&
|
|
36268
|
+
!this.form.invalid && !this.form.pending && this.projectFilterValues(this.form.getRawValue()) !== null;
|
|
36269
|
+
}
|
|
36270
|
+
projectFilterValues(value) {
|
|
36271
|
+
let payload = { ...value };
|
|
36272
|
+
for (const field of this.fieldMetadata) {
|
|
36273
|
+
if (field.submitPolicy === 'omit') {
|
|
36274
|
+
if (field.name.includes('.'))
|
|
36275
|
+
payload = deleteNestedPath(payload, field.name);
|
|
36276
|
+
else
|
|
36277
|
+
delete payload[field.name];
|
|
36278
|
+
continue;
|
|
36279
|
+
}
|
|
36280
|
+
if (field.items && hasNestedPath(payload, field.name)) {
|
|
36281
|
+
const normalized = normalizeScalarArrayValue(getNestedPath(payload, field.name), field.items);
|
|
36282
|
+
if (!normalized.valid)
|
|
36283
|
+
return null;
|
|
36284
|
+
if (field.name.includes('.'))
|
|
36285
|
+
payload = setNestedPath(payload, field.name, normalized.value);
|
|
36286
|
+
else
|
|
36287
|
+
payload[field.name] = normalized.value;
|
|
36288
|
+
}
|
|
36289
|
+
}
|
|
36290
|
+
return payload;
|
|
34462
36291
|
}
|
|
34463
36292
|
getColumnFields(column) {
|
|
34464
36293
|
const cached = this.columnFieldsCache.get(column);
|
|
@@ -35070,8 +36899,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
35070
36899
|
}] } });
|
|
35071
36900
|
|
|
35072
36901
|
var praxisFilterFormWidgetConfigEditor = /*#__PURE__*/Object.freeze({
|
|
35073
|
-
|
|
35074
|
-
|
|
36902
|
+
__proto__: null,
|
|
36903
|
+
PraxisFilterFormWidgetConfigEditor: PraxisFilterFormWidgetConfigEditor
|
|
35075
36904
|
});
|
|
35076
36905
|
|
|
35077
36906
|
/** Project explicit editor changes over authored input, preserving deletions and transient defaults. */
|
|
@@ -35719,8 +37548,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
35719
37548
|
}] } });
|
|
35720
37549
|
|
|
35721
37550
|
var praxisDynamicFormWidgetConfigEditor = /*#__PURE__*/Object.freeze({
|
|
35722
|
-
|
|
35723
|
-
|
|
37551
|
+
__proto__: null,
|
|
37552
|
+
PraxisDynamicFormWidgetConfigEditor: PraxisDynamicFormWidgetConfigEditor
|
|
35724
37553
|
});
|
|
35725
37554
|
|
|
35726
37555
|
// Owner-qualified dictionary keys work through the registry's existing editorial
|
|
@@ -36031,7 +37860,9 @@ const PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA = {
|
|
|
36031
37860
|
description: 'Configuracao completa do formulario (layout, metadados, acoes, regras e headers de secao com `sectionHeader` para icone/avatar dinamico e `headerActions` para acoes contextuais).',
|
|
36032
37861
|
},
|
|
36033
37862
|
{ name: 'actions', type: "FormConfig['actions'] | null", label: 'Ações', description: 'Overrides de apresentação da barra de ações fornecidos pelo host; preservam schema, método e endpoint canônicos.' },
|
|
36034
|
-
{ name: 'schemaSource', type: "'resource' | 'filter'", default: 'resource', description: 'Fonte do schema de campos' },
|
|
37863
|
+
{ name: 'schemaSource', type: "'resource' | 'filter' | 'action'", default: 'resource', description: 'Fonte do schema de campos' },
|
|
37864
|
+
{ name: 'actionId', type: 'string | null', description: 'Identificador canônico da ação de workflow ou comando governado associado ao formulário' },
|
|
37865
|
+
{ name: 'operationId', type: 'string | null', description: 'OperationId canônico publicado pelo catálogo de ações ou surfaces para execução do comando' },
|
|
36035
37866
|
{ name: 'schemaUrl', type: 'string | null', description: 'Schema canonico explicito publicado pelo backend (ex.: surfaces/capabilities)' },
|
|
36036
37867
|
{ name: 'readUrl', type: 'string | null', description: 'URL canonica de leitura publicada por surfaces VIEW/READ_PROJECTION' },
|
|
36037
37868
|
{ name: 'apiEndpointKey', type: 'ApiEndpoint | string | null', description: 'Endpoint canonico usado para resolver schemaUrl, readUrl e submitUrl relativos em hosts destacados' },
|
|
@@ -39118,8 +40949,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
39118
40949
|
}] } });
|
|
39119
40950
|
|
|
39120
40951
|
var sectionEditor_component = /*#__PURE__*/Object.freeze({
|
|
39121
|
-
|
|
39122
|
-
|
|
40952
|
+
__proto__: null,
|
|
40953
|
+
SectionEditorComponent: SectionEditorComponent
|
|
39123
40954
|
});
|
|
39124
40955
|
|
|
39125
40956
|
class RowEditorComponent {
|
|
@@ -39492,8 +41323,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
39492
41323
|
}] }] });
|
|
39493
41324
|
|
|
39494
41325
|
var rowEditor_component = /*#__PURE__*/Object.freeze({
|
|
39495
|
-
|
|
39496
|
-
|
|
41326
|
+
__proto__: null,
|
|
41327
|
+
RowEditorComponent: RowEditorComponent
|
|
39497
41328
|
});
|
|
39498
41329
|
|
|
39499
41330
|
class ColumnEditorComponent {
|
|
@@ -40201,8 +42032,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
40201
42032
|
}] }] });
|
|
40202
42033
|
|
|
40203
42034
|
var columnEditor_component = /*#__PURE__*/Object.freeze({
|
|
40204
|
-
|
|
40205
|
-
|
|
42035
|
+
__proto__: null,
|
|
42036
|
+
ColumnEditorComponent: ColumnEditorComponent
|
|
40206
42037
|
});
|
|
40207
42038
|
|
|
40208
42039
|
class FieldEditorComponent {
|
|
@@ -41196,4 +43027,4 @@ function nativePath(value) {
|
|
|
41196
43027
|
* Generated bundle index. Do not edit.
|
|
41197
43028
|
*/
|
|
41198
43029
|
|
|
41199
|
-
export { ActionsEditorComponent, CORPORATE_PRESENTATION_FORMAT_GALLERY, CanvasStateService, CanvasToolbarComponent, ColumnEditorComponent, DYNAMIC_FORM_GOVERNED_PAGE_PREVIEW_ADAPTER, DomainRuleFormRulesService, DynamicFormLayoutService, DynamicFormSchemaCacheService, ERGADM00034_COMPACT_PRESENTATION_EXAMPLE, Ergadm00034CompactPresentationExampleComponent, FORM_AI_CAPABILITIES, FORM_COMPONENT_AI_CAPABILITIES, FieldConfiguratorComponent, FieldEditorComponent, FormConfigService, FormContextService, FormLayoutService, FormRulesService, JsonConfigEditorComponent, LayoutColorToken, LayoutEditorComponent, LayoutPrefsService, PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST, PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA, PRAXIS_FILTER_FORM_AUTHORING_MANIFEST, PRAXIS_FILTER_FORM_AUTHORING_PROJECTION, PRAXIS_FILTER_FORM_COMPONENT_METADATA, PraxisDynamicForm, PraxisDynamicFormConfigEditor, PraxisDynamicFormWidgetConfigEditor, PraxisFilterForm, PraxisFilterFormWidgetConfigEditor, PraxisFormActionsComponent, RowConfiguratorComponent, RowEditorComponent, SETTINGS_PANEL_DYNAMIC_FORM_PROVIDER, SectionEditorComponent, TASK_PRESETS, applyVisibilityRules, buildCorporatePresentationFormatGalleryConfig, buildDynamicFormApplyPlan, buildDynamicFormRuleAuthoringContext, buildErgadm00034CompactPresentationConfig, createDynamicFormAuthoringDocument, decodeDynamicFormPageInputs, encodeDynamicFormPageInputs, formLayoutRulesToBuilderState, getFormAiCatalog, getFormCapabilities, getFormEnum, isRuleSatisfied, materializeDynamicFormPageRuntimeInputs, normalizeDateArrays, normalizeDynamicFormAuthoringDocument, parseLegacyOrDynamicFormDocument, projectDynamicFormPageEditorChanges, providePraxisDynamicFormMetadata, providePraxisFilterFormMetadata, provideSettingsPanelDynamicForm, ruleBuilderStateToFormLayoutRules, serializeDynamicFormAuthoringDocument, stripLegacyFieldMetadata, toCanonicalDynamicFormConfig, validateDynamicFormAuthoringDocument, validateDynamicFormAuthoringInput, validateDynamicFormPageWidget };
|
|
43030
|
+
export { ActionsEditorComponent, CORPORATE_PRESENTATION_FORMAT_GALLERY, CanvasStateService, CanvasToolbarComponent, ColumnEditorComponent, DYNAMIC_FORM_GOVERNED_PAGE_PREVIEW_ADAPTER, DomainRuleFormRulesService, DynamicFormLayoutService, DynamicFormSchemaCacheService, ERGADM00034_COMPACT_PRESENTATION_EXAMPLE, Ergadm00034CompactPresentationExampleComponent, FORM_AI_CAPABILITIES, FORM_COMPONENT_AI_CAPABILITIES, FieldConfiguratorComponent, FieldEditorComponent, FormConfigService, FormContextService, FormLayoutService, FormRulesService, JsonConfigEditorComponent, LayoutColorToken, LayoutEditorComponent, LayoutPrefsService, PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST, PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA, PRAXIS_FILTER_FORM_AUTHORING_MANIFEST, PRAXIS_FILTER_FORM_AUTHORING_PROJECTION, PRAXIS_FILTER_FORM_COMPONENT_METADATA, PraxisDynamicForm, PraxisDynamicFormConfigEditor, PraxisDynamicFormWidgetConfigEditor, PraxisFilterForm, PraxisFilterFormWidgetConfigEditor, PraxisFormActionsComponent, RowConfiguratorComponent, RowEditorComponent, SETTINGS_PANEL_DYNAMIC_FORM_PROVIDER, SectionEditorComponent, TASK_PRESETS, applyVisibilityRules, buildCorporatePresentationFormatGalleryConfig, buildDynamicFormApplyPlan, buildDynamicFormRuleAuthoringContext, buildErgadm00034CompactPresentationConfig, createDynamicFormAuthoringDocument, decodeDynamicFormPageInputs, encodeDynamicFormPageInputs, formLayoutRulesToBuilderState, getFormAiCatalog, getFormCapabilities, getFormEnum, isRuleSatisfied, materializeDynamicFormPageRuntimeInputs, normalizeDateArrays, normalizeDynamicFormAuthoringDocument, normalizeTemporalFieldValues, parseLegacyOrDynamicFormDocument, projectDynamicFormPageEditorChanges, providePraxisDynamicFormMetadata, providePraxisFilterFormMetadata, provideSettingsPanelDynamicForm, ruleBuilderStateToFormLayoutRules, serializeDynamicFormAuthoringDocument, stripLegacyFieldMetadata, toCanonicalDynamicFormConfig, validateDynamicFormAuthoringDocument, validateDynamicFormAuthoringInput, validateDynamicFormPageWidget };
|