@praxisui/dynamic-form 9.0.0-beta.26 → 9.0.0-beta.28
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 +2 -0
- package/ai/component-registry.json +76 -12
- package/fesm2022/praxisui-dynamic-form.mjs +81 -12
- package/package.json +8 -8
- package/src/lib/config-editor/praxis-dynamic-form-config-editor.json-api.md +5 -5
- package/src/lib/praxis-dynamic-form.json-api.md +4 -4
- package/types/praxisui-dynamic-form.d.ts +9 -3
|
@@ -21,9 +21,9 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
|
21
21
|
import * as i18 from '@angular/material/badge';
|
|
22
22
|
import { MatBadgeModule } from '@angular/material/badge';
|
|
23
23
|
import { map, firstValueFrom, BehaviorSubject, Subject, throwError, Subscription, combineLatest, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs';
|
|
24
|
-
import { map as map$1,
|
|
24
|
+
import { map as map$1, takeUntil, skip, take, timeout, tap, debounceTime, startWith, finalize } from 'rxjs/operators';
|
|
25
25
|
import * as i1 from '@praxisui/core';
|
|
26
|
-
import { serializeEntityLookupValueForPayload, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, migrateFormLayoutRule, PraxisJsonLogicService, normalizeFormLayoutItems, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, isPraxisRuntimeGlobalActionEffect, ASYNC_CONFIG_STORAGE, createFieldLayoutItem, getFormLayoutFieldNames, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, GlobalActionService, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, mapFieldDefinitionsToMetadata, reconcileFormConfig, materializeFormLayoutFromMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, normalizeControlTypeKey, normalizePraxisEffectPolicy, buildPraxisEffectDistinctKey, getFormColumnFieldNames, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaIdStorageKeySegment, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, API_URL, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, isRequiredGlobalActionPayloadMissing, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, validateGlobalActionRefs, normalizeFormMetadata } from '@praxisui/core';
|
|
26
|
+
import { serializeEntityLookupValueForPayload, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, migrateFormLayoutRule, PraxisJsonLogicService, normalizeFormLayoutItems, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, isPraxisRuntimeGlobalActionEffect, ASYNC_CONFIG_STORAGE, createFieldLayoutItem, getFormLayoutFieldNames, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, GlobalActionService, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, mapFieldDefinitionsToMetadata, reconcileFormConfig, materializeFormLayoutFromMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, evaluateFieldAccess, normalizeControlTypeKey, normalizePraxisEffectPolicy, buildPraxisEffectDistinctKey, getFormColumnFieldNames, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaIdStorageKeySegment, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, API_URL, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, isRequiredGlobalActionPayloadMissing, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, validateGlobalActionRefs, normalizeFormMetadata } from '@praxisui/core';
|
|
27
27
|
import * as i1$1 from '@praxisui/dynamic-fields';
|
|
28
28
|
import { getControlTypeCatalog, ConfirmDialogComponent, DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
|
|
29
29
|
import { BaseAiAdapter, AiBackendApiService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnOrchestratorService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
|
|
@@ -2322,7 +2322,6 @@ const FORM_AI_CAPABILITIES = {
|
|
|
2322
2322
|
'praxis-row-configurator',
|
|
2323
2323
|
'praxis-field-configurator',
|
|
2324
2324
|
'praxis-behavior-editor',
|
|
2325
|
-
'praxis-rules-editor',
|
|
2326
2325
|
'praxis-section-preset-picker'
|
|
2327
2326
|
],
|
|
2328
2327
|
notes: [
|
|
@@ -3997,10 +3996,10 @@ const FORM_AI_CAPABILITIES = {
|
|
|
3997
3996
|
...generateRulePropertyWhenFalseCapabilities(FormRuleTargetType.VisualBlock, RULE_PROPERTY_SCHEMA.visualBlock),
|
|
3998
3997
|
{
|
|
3999
3998
|
path: 'formRulesState',
|
|
4000
|
-
category: '
|
|
3999
|
+
category: 'metadata',
|
|
4001
4000
|
valueKind: 'object',
|
|
4002
|
-
description: 'Estado interno do builder de regras
|
|
4003
|
-
safetyNotes: '
|
|
4001
|
+
description: 'Estado interno do builder visual de regras, gerado apenas para round-trip do editor.',
|
|
4002
|
+
safetyNotes: 'Read-only/internal. Não use como alvo de autoria, patch, exemplo ou operação de IA; gere somente formRules e deixe o editor materializar formRulesState.',
|
|
4004
4003
|
},
|
|
4005
4004
|
// =============================================================================
|
|
4006
4005
|
// FORM CONFIG - HOOKS
|
|
@@ -10440,6 +10439,7 @@ class PraxisDynamicForm {
|
|
|
10440
10439
|
hooksRegistry;
|
|
10441
10440
|
hookPresets;
|
|
10442
10441
|
logger;
|
|
10442
|
+
enterpriseRuntimeContext;
|
|
10443
10443
|
i18n = inject(PraxisI18nService);
|
|
10444
10444
|
injector = inject(Injector);
|
|
10445
10445
|
aiApi = inject(AiBackendApiService);
|
|
@@ -11143,7 +11143,8 @@ class PraxisDynamicForm {
|
|
|
11143
11143
|
// Avoids duplicate standalone bootstrap when the form was already mounted
|
|
11144
11144
|
// programmatically before the first ngOnInit/detectChanges cycle.
|
|
11145
11145
|
hasBuiltFormFromConfig = false;
|
|
11146
|
-
|
|
11146
|
+
runtimeFieldMetadata = null;
|
|
11147
|
+
constructor(crud, http, fb, cdr, layoutService, contextService, rulesService, settingsPanel, dialog, asyncConfigStorage, connectionStorage, dynamicForm, snackBar, canvasState, dynamicLayout, errorMessages, schemaNormalizer, componentMetaRegistry, global, componentKeys, loadingOrchestrator, ngZone, apiUrlConfig, loadingRenderer, router, route, hooksRegistry, hookPresets, logger, enterpriseRuntimeContext) {
|
|
11147
11148
|
this.crud = crud;
|
|
11148
11149
|
this.http = http;
|
|
11149
11150
|
this.fb = fb;
|
|
@@ -11173,6 +11174,7 @@ class PraxisDynamicForm {
|
|
|
11173
11174
|
this.hooksRegistry = hooksRegistry;
|
|
11174
11175
|
this.hookPresets = hookPresets;
|
|
11175
11176
|
this.logger = logger;
|
|
11177
|
+
this.enterpriseRuntimeContext = enterpriseRuntimeContext;
|
|
11176
11178
|
this.form = this.fb.group({});
|
|
11177
11179
|
this.aiAdapter = new FormAiAdapter(this);
|
|
11178
11180
|
this.debugLog('[PDF] ctor inputs', {
|
|
@@ -11539,6 +11541,20 @@ class PraxisDynamicForm {
|
|
|
11539
11541
|
if (!this.formId && !this.resourcePath && this.hasRenderableConfig()) {
|
|
11540
11542
|
this.initializeStandaloneConfig();
|
|
11541
11543
|
}
|
|
11544
|
+
this.enterpriseRuntimeContext?.contextChanges$
|
|
11545
|
+
.pipe(takeUntil(this.destroy$), skip(1))
|
|
11546
|
+
.subscribe(() => {
|
|
11547
|
+
this.runtimeFieldMetadata = null;
|
|
11548
|
+
if (this.hasBuiltFormFromConfig && this.hasRenderableConfig()) {
|
|
11549
|
+
this.buildFormFromConfig({
|
|
11550
|
+
reason: 'runtime-context',
|
|
11551
|
+
preserveRuntimeState: true,
|
|
11552
|
+
preserveInteractionState: true,
|
|
11553
|
+
fallbackToLoadedEntity: true,
|
|
11554
|
+
});
|
|
11555
|
+
this.cdr.markForCheck();
|
|
11556
|
+
}
|
|
11557
|
+
});
|
|
11542
11558
|
// Load persisted connection if not provided via input
|
|
11543
11559
|
const connKey = this.connectionKey();
|
|
11544
11560
|
if (!this.resourcePath && connKey) {
|
|
@@ -12231,7 +12247,8 @@ class PraxisDynamicForm {
|
|
|
12231
12247
|
});
|
|
12232
12248
|
}
|
|
12233
12249
|
buildFormFromConfig(options = { reason: 'initialization' }) {
|
|
12234
|
-
|
|
12250
|
+
this.runtimeFieldMetadata = null;
|
|
12251
|
+
const fieldMetadata = this.getRuntimeFieldMetadata();
|
|
12235
12252
|
const previousState = options.preserveRuntimeState
|
|
12236
12253
|
? this.captureFormRuntimeState()
|
|
12237
12254
|
: null;
|
|
@@ -12442,6 +12459,56 @@ class PraxisDynamicForm {
|
|
|
12442
12459
|
const label = String(field.label || field.name || 'entidade').trim();
|
|
12443
12460
|
return `Selecione um valor valido para ${label} no contexto atual.`;
|
|
12444
12461
|
}
|
|
12462
|
+
getRuntimeFieldMetadata() {
|
|
12463
|
+
const source = this.config?.fieldMetadata || [];
|
|
12464
|
+
if (!source.length) {
|
|
12465
|
+
this.runtimeFieldMetadata = source;
|
|
12466
|
+
return source;
|
|
12467
|
+
}
|
|
12468
|
+
if (this.runtimeFieldMetadata) {
|
|
12469
|
+
return this.runtimeFieldMetadata;
|
|
12470
|
+
}
|
|
12471
|
+
const authorities = this.resolveFieldAccessAuthorities();
|
|
12472
|
+
this.runtimeFieldMetadata = source.map((field) => this.materializeFieldAccessState(field, authorities));
|
|
12473
|
+
return this.runtimeFieldMetadata;
|
|
12474
|
+
}
|
|
12475
|
+
resolveFieldAccessAuthorities() {
|
|
12476
|
+
const metadata = this.config?.metadata;
|
|
12477
|
+
const configuredAuthorities = this.normalizeAuthorityClaims(metadata?.fieldAccessAuthorities ?? metadata?.authorities);
|
|
12478
|
+
if (configuredAuthorities) {
|
|
12479
|
+
return configuredAuthorities;
|
|
12480
|
+
}
|
|
12481
|
+
return this.normalizeAuthorityClaims(this.enterpriseRuntimeContext?.snapshot?.authorities);
|
|
12482
|
+
}
|
|
12483
|
+
normalizeAuthorityClaims(value) {
|
|
12484
|
+
if (!Array.isArray(value)) {
|
|
12485
|
+
return null;
|
|
12486
|
+
}
|
|
12487
|
+
return Array.from(new Set(value
|
|
12488
|
+
.filter((item) => typeof item === 'string')
|
|
12489
|
+
.map((item) => item.trim())
|
|
12490
|
+
.filter(Boolean)));
|
|
12491
|
+
}
|
|
12492
|
+
materializeFieldAccessState(field, authorities) {
|
|
12493
|
+
const access = evaluateFieldAccess(field, { authorities });
|
|
12494
|
+
if (!access.evaluated) {
|
|
12495
|
+
return field;
|
|
12496
|
+
}
|
|
12497
|
+
const hiddenByAccess = !access.visible;
|
|
12498
|
+
const readonlyByAccess = access.visible && !access.editable;
|
|
12499
|
+
if (!hiddenByAccess && !readonlyByAccess) {
|
|
12500
|
+
return field;
|
|
12501
|
+
}
|
|
12502
|
+
return {
|
|
12503
|
+
...field,
|
|
12504
|
+
...(hiddenByAccess
|
|
12505
|
+
? { hidden: true, formHidden: true, disabled: true }
|
|
12506
|
+
: {}),
|
|
12507
|
+
...(readonlyByAccess
|
|
12508
|
+
? { readOnly: true, disabled: true }
|
|
12509
|
+
: {}),
|
|
12510
|
+
};
|
|
12511
|
+
}
|
|
12445
12512
|
scheduleValueChangeBootstrapRelease(buildCycleId) {
|
|
12446
12513
|
queueMicrotask(() => {
|
|
12447
12514
|
this.ngZone.onStable.pipe(take(1), takeUntil(this.destroy$)).subscribe(() => {
|
|
@@ -12901,7 +12968,7 @@ class PraxisDynamicForm {
|
|
|
12901
12968
|
...evaluated.formData,
|
|
12902
12969
|
...(evaluated.fieldValues || {}),
|
|
12903
12970
|
});
|
|
12904
|
-
const fieldMetadata = this.
|
|
12971
|
+
const fieldMetadata = this.getRuntimeFieldMetadata();
|
|
12905
12972
|
const fieldByName = new Map(fieldMetadata.map((f) => [f.name, f]));
|
|
12906
12973
|
for (const field of fieldMetadata) {
|
|
12907
12974
|
const overrides = this.fieldRuleProps[field.name] || {};
|
|
@@ -13180,7 +13247,7 @@ class PraxisDynamicForm {
|
|
|
13180
13247
|
column: new Set(),
|
|
13181
13248
|
visualBlock: new Set(),
|
|
13182
13249
|
};
|
|
13183
|
-
|
|
13250
|
+
this.getRuntimeFieldMetadata()
|
|
13184
13251
|
.filter((field) => !field?.formHidden)
|
|
13185
13252
|
.forEach((field) => {
|
|
13186
13253
|
if (field.name)
|
|
@@ -13916,7 +13983,7 @@ class PraxisDynamicForm {
|
|
|
13916
13983
|
if (cached?.signature === signature) {
|
|
13917
13984
|
return cached.value;
|
|
13918
13985
|
}
|
|
13919
|
-
const fieldMetadata = this.
|
|
13986
|
+
const fieldMetadata = this.getRuntimeFieldMetadata();
|
|
13920
13987
|
const byName = new Map(fieldMetadata.map((f) => [f.name, f]));
|
|
13921
13988
|
const ordered = [];
|
|
13922
13989
|
for (const name of fieldNames) {
|
|
@@ -18909,7 +18976,7 @@ class PraxisDynamicForm {
|
|
|
18909
18976
|
this.config = normalizeFormConfig$1(this.config);
|
|
18910
18977
|
}
|
|
18911
18978
|
}
|
|
18912
|
-
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: 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: i12.Router, optional: true }, { token: i12.ActivatedRoute, optional: true }, { token: i1.FormHooksRegistry, optional: true }, { token: FORM_HOOKS_PRESETS, optional: true }, { token: i1.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
18979
|
+
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: 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: i12.Router, optional: true }, { token: i12.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 });
|
|
18913
18980
|
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", editorialContext: "editorialContext", mode: "mode", config: "config", actions: "actions", schemaSource: "schemaSource", schemaUrl: "schemaUrl", readUrl: "readUrl", submitUrl: "submitUrl", submitMethod: "submitMethod", responseSchemaUrl: "responseSchemaUrl", apiEndpointKey: "apiEndpointKey", apiUrlEntry: "apiUrlEntry", enableCustomization: "enableCustomization", showAiAssistant: "showAiAssistant", formId: "formId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", layout: "layout", 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", visibleGlobal: "visibleGlobal", fieldIconPolicy: "fieldIconPolicy", domainRules: "domainRules", customEndpoints: "customEndpoints" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formReset: "formReset", configChange: "configChange", configPatchChange: "configPatchChange", formReady: "formReady", valueChange: "valueChange", syncCompleted: "syncCompleted", initializationError: "initializationError", loadingStateChange: "loadingStateChange", enableCustomizationChange: "enableCustomizationChange", customAction: "customAction", actionConfirmation: "actionConfirmation", schemaStatusChange: "schemaStatusChange", fieldRenderError: "fieldRenderError", ruleDiagnosticsChange: "ruleDiagnosticsChange" }, providers: [providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], viewQueries: [{ propertyName: "formHost", first: true, predicate: ["formHost"], descendants: true }, { propertyName: "fieldLoaders", predicate: DynamicFieldLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isLoading) {\n <!-- Loading State -->\n <div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\" 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\" mat-icon-button (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 <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\n </button>\n }\n <button type=\"button\" mat-icon-button (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configurar formul\u00E1rio'\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"disconnect()\" matTooltip=\"Desconectar da fonte de dados\"\n [disabled]=\"isLoading\">\n <mat-icon [praxisIcon]=\"'link_off'\"></mat-icon>\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && (!config.sections || config.sections.length === 0)) {\n <praxis-empty-state-card icon=\"link\" [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"></praxis-empty-state-card>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\" [class.readonly-mode]=\"effectiveReadonly\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n @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 @for (section of config.sections; track (section.id ?? $index); let sectionIndex = $index;\n let last = $last) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [style.marginBottom.px]=\"!last ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [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\" mat-icon-button (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n mat-icon-button\n [color]=\"getSectionHeaderActionColor(action)\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <mat-progress-spinner\n diameter=\"16\"\n mode=\"indeterminate\"\n [attr.aria-label]=\"getSectionHeaderActionLoadingLabel(action)\"\n ></mat-progress-spinner>\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n } @else {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" mat-icon-button\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n <mat-icon [praxisIcon]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\"></mat-icon>\n </button>\n }\n </div>\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"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 (last && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [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 @if (showAiAssistant && !enableCustomization && mode === 'view') {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" mat-icon-button (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\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 <mat-icon [praxisIcon]=\"'auto_awesome'\"></mat-icon>\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}@media(min-width:600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@media(min-width:900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@media(min-width:1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@media(min-width:1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:var(--praxis-layer-authoring-insert, 280)}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative;--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 .mat-icon-button{--mdc-icon-button-state-layer-size: 34px;width:34px;height:34px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);border:1px solid transparent}.form-config-controls .mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant 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}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,white 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;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 .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}}.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{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 .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.form-section.section-appearance-plain{border-color:transparent;border-radius:0;padding:0;background:transparent}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom: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;--mdc-icon-button-size: 28px;--mdc-icon-button-icon-size: 16px}.inline-edit-btn mat-icon{font-size:16px;width:16px;height:16px}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);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{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.form-row{flex-direction:column;gap:.5rem}.form-row.grid-12{grid-template-columns:minmax(0,1fr)}.form-row.grid-12>.column-drop-wrapper,.form-row.grid-12>.form-column,.form-row.grid-12 .form-column{grid-column:1/-1!important;margin-left:0;width:100%;max-width:100%;min-width:0}.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}\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.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", 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: i16.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: i18.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: CanvasToolbarComponent, selector: "praxis-canvas-toolbar", inputs: ["selectedElement"], outputs: ["editMetadata", "delete", "moveUp", "moveDown", "selectPath", "requestClose", "toggleReadonly", "toggleRequired", "toggleHidden", "toggleDisabled"] }, { kind: "component", type: PraxisFormActionsComponent, selector: "praxis-form-actions", inputs: ["actions", "editorialVisualContext", "isSubmitting", "formIsValid", "submitError", "invalidRequiredFieldLabels", "suppressInvalidSubmitHint", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { 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"] }] });
|
|
18914
18981
|
}
|
|
18915
18982
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicForm, decorators: [{
|
|
@@ -18959,6 +19026,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
18959
19026
|
args: [FORM_HOOKS_PRESETS]
|
|
18960
19027
|
}] }, { type: i1.LoggerService, decorators: [{
|
|
18961
19028
|
type: Optional
|
|
19029
|
+
}] }, { type: i1.EnterpriseRuntimeContextService, decorators: [{
|
|
19030
|
+
type: Optional
|
|
18962
19031
|
}] }], propDecorators: { resourcePath: [{
|
|
18963
19032
|
type: Input
|
|
18964
19033
|
}], resourceId: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/dynamic-form",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.28",
|
|
4
4
|
"description": "Angular dynamic form engine for Praxis UI: metadata-driven forms, hooks, and services integrating @praxisui/* packages.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"@angular/forms": "^21.0.0",
|
|
10
10
|
"@angular/material": "^21.0.0",
|
|
11
11
|
"@angular/router": "^21.0.0",
|
|
12
|
-
"@praxisui/ai": "^9.0.0-beta.
|
|
13
|
-
"@praxisui/dynamic-fields": "^9.0.0-beta.
|
|
14
|
-
"@praxisui/metadata-editor": "^9.0.0-beta.
|
|
15
|
-
"@praxisui/rich-content": "^9.0.0-beta.
|
|
16
|
-
"@praxisui/settings-panel": "^9.0.0-beta.
|
|
17
|
-
"@praxisui/visual-builder": "^9.0.0-beta.
|
|
18
|
-
"@praxisui/core": "^9.0.0-beta.
|
|
12
|
+
"@praxisui/ai": "^9.0.0-beta.28",
|
|
13
|
+
"@praxisui/dynamic-fields": "^9.0.0-beta.28",
|
|
14
|
+
"@praxisui/metadata-editor": "^9.0.0-beta.28",
|
|
15
|
+
"@praxisui/rich-content": "^9.0.0-beta.28",
|
|
16
|
+
"@praxisui/settings-panel": "^9.0.0-beta.28",
|
|
17
|
+
"@praxisui/visual-builder": "^9.0.0-beta.28",
|
|
18
|
+
"@praxisui/core": "^9.0.0-beta.28",
|
|
19
19
|
"rxjs": "^7.8.0"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
@@ -103,7 +103,7 @@ Este documento e a referencia canonica da API JSON de praxis-dynamic-form-config
|
|
|
103
103
|
| `messages` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
104
104
|
| `hooks` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
105
105
|
| `formRules` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
106
|
-
| `formRulesState` |
|
|
106
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
107
107
|
| `hints` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
108
108
|
| `api` | not-specified | not-specified | n/a | Partial | Preservado da documentação anterior. |
|
|
109
109
|
| `metadata` | not-specified | not-specified | n/a | Partial | Preservado da documentação anterior. |
|
|
@@ -141,7 +141,7 @@ Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecn
|
|
|
141
141
|
| messages | Configuração top-level identificada na referência preservada. | not-yet-verified | component-defined | 1 path(s) mapeado(s), status predominante Active. |
|
|
142
142
|
| hooks | Configuração top-level identificada na referência preservada. | not-yet-verified | component-defined | 1 path(s) mapeado(s), status predominante Active. |
|
|
143
143
|
| formRules | Configuração top-level identificada na referência preservada. | not-yet-verified | component-defined | 1 path(s) mapeado(s), status predominante Active. |
|
|
144
|
-
| formRulesState |
|
|
144
|
+
| formRulesState | Estado interno de round-trip do builder visual. | verified | internal-derived | Gerado pelo editor a partir de `formRules`; nao escrever diretamente. |
|
|
145
145
|
|
|
146
146
|
### Nested configuration blocks
|
|
147
147
|
|
|
@@ -154,7 +154,7 @@ Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecn
|
|
|
154
154
|
| `messages` | not-specified | not-specified | n/a | component-defined | Preservado da documentação anterior. |
|
|
155
155
|
| `hooks` | not-specified | not-specified | n/a | component-defined | Preservado da documentação anterior. |
|
|
156
156
|
| `formRules` | not-specified | not-specified | n/a | component-defined | Preservado da documentação anterior. |
|
|
157
|
-
| `formRulesState` |
|
|
157
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | internal-derived | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
158
158
|
| `hints` | not-specified | not-specified | n/a | component-defined | Preservado da documentação anterior. |
|
|
159
159
|
| `api` | not-specified | not-specified | n/a | component-defined | Preservado da documentação anterior. |
|
|
160
160
|
|
|
@@ -331,7 +331,7 @@ A entrada operacional vem via `SETTINGS_PANEL_DATA` (injetado pelo settings pane
|
|
|
331
331
|
| `messages` | Active | Editado na aba Mensagens. |
|
|
332
332
|
| `hooks` | Active | Editado na aba Hooks e JSON. |
|
|
333
333
|
| `formRules` | Active | Gerado pela aba Regras (visual builder). |
|
|
334
|
-
| `formRulesState` |
|
|
334
|
+
| `formRulesState` | Internal | Persistido somente como estado de round-trip do builder visual; nao e contrato autoravel. |
|
|
335
335
|
| `hints` | Active | Editado na aba Dicas e Tooltips. |
|
|
336
336
|
| `api` | Partial | Sem aba dedicada; passa por JSON editor quando presente. |
|
|
337
337
|
| `metadata` | Partial | Mantido em round-trip; sem painel dedicado. |
|
|
@@ -412,7 +412,7 @@ Correcao: e diff estrutural para UX do painel, nao auditoria de negocio.
|
|
|
412
412
|
| `messages` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
413
413
|
| `hooks` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
414
414
|
| `formRules` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
415
|
-
| `formRulesState` |
|
|
415
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
416
416
|
| `hints` | not-specified | not-specified | n/a | Active | Preservado da documentação anterior. |
|
|
417
417
|
| `api` | not-specified | not-specified | n/a | Partial | Preservado da documentação anterior. |
|
|
418
418
|
| `metadata` | not-specified | not-specified | n/a | Partial | Preservado da documentação anterior. |
|
|
@@ -129,7 +129,7 @@ Essa fronteira preserva a premissa de plataforma: o formulario materializa e exp
|
|
|
129
129
|
| `messages` | not-specified | not-specified | n/a | Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
|
|
130
130
|
| `formRules` | not-specified | not-specified | n/a | Active | Aplicadas no pipeline de regras do runtime. |
|
|
131
131
|
| `formCommandRules` | not-specified | not-specified | n/a | Active | Regras condicionais de comando avaliadas sobre `formData` estabilizado depois de `formRules`; primeiro corte suporta `global-action`. |
|
|
132
|
-
| `formRulesState` |
|
|
132
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
133
133
|
| `hooks` | not-specified | not-specified | n/a | Active | Integracao de ciclo (before/after) via runtime de hooks. |
|
|
134
134
|
| `hints` | not-specified | not-specified | n/a | Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
|
|
135
135
|
| `helpPresentation` | `FormHelpPresentationConfig` | No | `{ display: "inline" }` | Active | Politica visual para exibir `hint`/`helpText` dos campos sem alterar semantica dos DTOs; erros de validacao continuam inline. |
|
|
@@ -193,7 +193,7 @@ Este arquivo foi adaptado para o padrao canonico atual sem remover conteudo tecn
|
|
|
193
193
|
| `api` | not-specified | not-specified | n/a | component-defined | Declarado no modelo; sem binding operacional direto no runtime atual. |
|
|
194
194
|
| `messages` | not-specified | not-specified | n/a | component-defined | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
|
|
195
195
|
| `formRules` | not-specified | not-specified | n/a | component-defined | Aplicadas no pipeline de regras do runtime. |
|
|
196
|
-
| `formRulesState` |
|
|
196
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | internal-derived | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
197
197
|
| `hooks` | not-specified | not-specified | n/a | component-defined | Integracao de ciclo (before/after) via runtime de hooks. |
|
|
198
198
|
| `sections[].sectionHeader` | `FormSectionHeaderConfig` | No | n/a | Active | Header visual rico da seção com suporte a avatar dinâmico resolvido a partir de `formData`. |
|
|
199
199
|
|
|
@@ -709,7 +709,7 @@ Precedencias importantes:
|
|
|
709
709
|
| `api` | Declared-only | Declarado no modelo; sem binding operacional direto no runtime atual. |
|
|
710
710
|
| `messages` | Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
|
|
711
711
|
| `formRules` | Active | Aplicadas no pipeline de regras do runtime. |
|
|
712
|
-
| `formRulesState` |
|
|
712
|
+
| `formRulesState` | Internal | Persistido somente como estado de round-trip do builder visual; nao e contrato autoravel. |
|
|
713
713
|
| `hooks` | Active | Integracao de ciclo (before/after) via runtime de hooks. |
|
|
714
714
|
| `hints` | Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
|
|
715
715
|
|
|
@@ -886,7 +886,7 @@ O runtime emite `target-not-found` quando uma regra aponta para `section`, `row`
|
|
|
886
886
|
| `api` | not-specified | not-specified | n/a | Declared-only | Declarado no modelo; sem binding operacional direto no runtime atual. |
|
|
887
887
|
| `messages` | not-specified | not-specified | n/a | Partial | Chaves principais de submit/confirmacao usadas; contrato e mais amplo. |
|
|
888
888
|
| `formRules` | not-specified | not-specified | n/a | Active | Aplicadas no pipeline de regras do runtime. |
|
|
889
|
-
| `formRulesState` |
|
|
889
|
+
| `formRulesState` | internal-round-trip | Gerado pelo builder visual; nao e alvo de autoria manual ou IA. | n/a | Internal | Estado visual derivado de `formRules` para reabertura do editor. |
|
|
890
890
|
| `hooks` | not-specified | not-specified | n/a | Active | Integracao de ciclo (before/after) via runtime de hooks. |
|
|
891
891
|
| `hints` | not-specified | not-specified | n/a | Declared-only | Mantido no contrato/editor; sem render dedicado no template principal. |
|
|
892
892
|
|
|
@@ -7,7 +7,7 @@ import { MatDialog } from '@angular/material/dialog';
|
|
|
7
7
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
8
8
|
import { CdkDragStart, CdkDragMove, CdkDragEnd, CdkDragDrop } from '@angular/cdk/drag-drop';
|
|
9
9
|
import * as _praxisui_core from '@praxisui/core';
|
|
10
|
-
import { AsyncConfigStorage, FormLayout, FieldMetadata, FormLayoutRule, FormRuleTargetType as FormRuleTargetType$1, PraxisJsonLogicService, FormSection, FormRow, FormColumn, FormConfig, FormLayoutItem, FormActionButton, AiCapability, BackConfig, RichBlockHostCapabilities, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, FormHooksLayout, EndpointConfig, FormSubmitEvent, FormReadyEvent, FormValueChangeEvent, SyncResult, FormInitializationError, LoadingState, FormCustomActionEvent, FormActionConfirmationEvent, RichContentDocument, JsonLogicRecord, GenericCrudService, ConnectionStorage, DynamicFormService, ErrorMessageService, SchemaNormalizerService, ComponentMetadataRegistry, GlobalConfigService, ComponentKeyService, LoadingOrchestrator, ApiUrlConfig, PraxisLoadingRenderer, FormHooksRegistry, FormHookPreset, LoggerService, FormSectionHeaderAction, FormSectionHeaderConfig, FormConfigState, JsonLogicExpression, FormHelpPresentationConfig, GlobalActionCatalogEntry, PraxisRuntimeConditionalEffectRule, PraxisRuntimeGlobalActionEffect, SurfaceOpenPayload, GlobalActionField, PraxisEffectPolicy, FieldDefinition, ComponentDocMeta, Breakpoint, DomainRuleRequestOptions, DomainRuleService, DomainRuleMaterialization, TableConfig, IconPickerService, GlobalActionRef, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest } from '@praxisui/core';
|
|
10
|
+
import { AsyncConfigStorage, FormLayout, FieldMetadata, FormLayoutRule, FormRuleTargetType as FormRuleTargetType$1, PraxisJsonLogicService, FormSection, FormRow, FormColumn, FormConfig, FormLayoutItem, FormActionButton, AiCapability, BackConfig, RichBlockHostCapabilities, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, FormHooksLayout, EndpointConfig, FormSubmitEvent, FormReadyEvent, FormValueChangeEvent, SyncResult, FormInitializationError, LoadingState, FormCustomActionEvent, FormActionConfirmationEvent, RichContentDocument, JsonLogicRecord, GenericCrudService, ConnectionStorage, DynamicFormService, ErrorMessageService, SchemaNormalizerService, ComponentMetadataRegistry, GlobalConfigService, ComponentKeyService, LoadingOrchestrator, ApiUrlConfig, PraxisLoadingRenderer, FormHooksRegistry, FormHookPreset, LoggerService, EnterpriseRuntimeContextService, FormSectionHeaderAction, FormSectionHeaderConfig, FormConfigState, JsonLogicExpression, FormHelpPresentationConfig, GlobalActionCatalogEntry, PraxisRuntimeConditionalEffectRule, PraxisRuntimeGlobalActionEffect, SurfaceOpenPayload, GlobalActionField, PraxisEffectPolicy, FieldDefinition, ComponentDocMeta, Breakpoint, DomainRuleRequestOptions, DomainRuleService, DomainRuleMaterialization, TableConfig, IconPickerService, GlobalActionRef, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest } from '@praxisui/core';
|
|
11
11
|
import * as rxjs from 'rxjs';
|
|
12
12
|
import { Observable, BehaviorSubject } from 'rxjs';
|
|
13
13
|
import { SettingsPanelService, SettingsValueProvider } from '@praxisui/settings-panel';
|
|
@@ -697,6 +697,7 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
|
|
|
697
697
|
private hooksRegistry?;
|
|
698
698
|
private hookPresets?;
|
|
699
699
|
private logger?;
|
|
700
|
+
private enterpriseRuntimeContext?;
|
|
700
701
|
private readonly i18n;
|
|
701
702
|
private readonly injector;
|
|
702
703
|
private readonly aiApi;
|
|
@@ -962,7 +963,8 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
|
|
|
962
963
|
private mountAnimationTimer;
|
|
963
964
|
protected isMounting: boolean;
|
|
964
965
|
private hasBuiltFormFromConfig;
|
|
965
|
-
|
|
966
|
+
private runtimeFieldMetadata;
|
|
967
|
+
constructor(crud: GenericCrudService<any>, http: HttpClient, fb: FormBuilder, cdr: ChangeDetectorRef, layoutService: FormLayoutService, contextService: FormContextService, rulesService: FormRulesService, settingsPanel: SettingsPanelService, dialog: MatDialog, asyncConfigStorage: AsyncConfigStorage, connectionStorage: ConnectionStorage, dynamicForm: DynamicFormService, snackBar: MatSnackBar, canvasState: CanvasStateService, dynamicLayout: DynamicFormLayoutService, errorMessages: ErrorMessageService, schemaNormalizer: SchemaNormalizerService, componentMetaRegistry: ComponentMetadataRegistry, global: GlobalConfigService, componentKeys: ComponentKeyService, loadingOrchestrator: LoadingOrchestrator, ngZone: NgZone, apiUrlConfig: ApiUrlConfig, loadingRenderer?: PraxisLoadingRenderer | undefined, router?: Router | undefined, route?: ActivatedRoute | undefined, hooksRegistry?: FormHooksRegistry | undefined, hookPresets?: FormHookPreset[] | null | undefined, logger?: LoggerService | undefined, enterpriseRuntimeContext?: EnterpriseRuntimeContextService | undefined);
|
|
966
968
|
private emitLoadingState;
|
|
967
969
|
private buildLoadingContext;
|
|
968
970
|
private beginLoading;
|
|
@@ -1026,6 +1028,10 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
|
|
|
1026
1028
|
private setEntityLookupDependencyConflict;
|
|
1027
1029
|
private clearEntityLookupDependencyConflict;
|
|
1028
1030
|
private resolveEntityLookupDependencyValidationMessage;
|
|
1031
|
+
private getRuntimeFieldMetadata;
|
|
1032
|
+
private resolveFieldAccessAuthorities;
|
|
1033
|
+
private normalizeAuthorityClaims;
|
|
1034
|
+
private materializeFieldAccessState;
|
|
1029
1035
|
private scheduleValueChangeBootstrapRelease;
|
|
1030
1036
|
private hasInteractiveFormState;
|
|
1031
1037
|
private captureFormRuntimeState;
|
|
@@ -1367,7 +1373,7 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
|
|
|
1367
1373
|
private logRowGapsSnapshot;
|
|
1368
1374
|
private applyPresentationVars;
|
|
1369
1375
|
private applyPresentationConfig;
|
|
1370
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisDynamicForm, [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
|
|
1376
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisDynamicForm, [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
|
|
1371
1377
|
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisDynamicForm, "praxis-dynamic-form", never, { "resourcePath": { "alias": "resourcePath"; "required": false; }; "resourceId": { "alias": "resourceId"; "required": false; }; "initialValue": { "alias": "initialValue"; "required": false; }; "editorialContext": { "alias": "editorialContext"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "config": { "alias": "config"; "required": false; }; "actions": { "alias": "actions"; "required": false; }; "schemaSource": { "alias": "schemaSource"; "required": false; }; "schemaUrl": { "alias": "schemaUrl"; "required": false; }; "readUrl": { "alias": "readUrl"; "required": false; }; "submitUrl": { "alias": "submitUrl"; "required": false; }; "submitMethod": { "alias": "submitMethod"; "required": false; }; "responseSchemaUrl": { "alias": "responseSchemaUrl"; "required": false; }; "apiEndpointKey": { "alias": "apiEndpointKey"; "required": false; }; "apiUrlEntry": { "alias": "apiUrlEntry"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "showAiAssistant": { "alias": "showAiAssistant"; "required": false; }; "formId": { "alias": "formId"; "required": false; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "configPersistenceStrategy": { "alias": "configPersistenceStrategy"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; "generatedLayoutPreset": { "alias": "generatedLayoutPreset"; "required": false; }; "layoutPolicy": { "alias": "layoutPolicy"; "required": false; }; "backConfig": { "alias": "backConfig"; "required": false; }; "hooks": { "alias": "hooks"; "required": false; }; "removeEmptyContainersOnSave": { "alias": "removeEmptyContainersOnSave"; "required": false; }; "reactiveValidation": { "alias": "reactiveValidation"; "required": false; }; "reactiveValidationDebounceMs": { "alias": "reactiveValidationDebounceMs"; "required": false; }; "notifyIfOutdated": { "alias": "notifyIfOutdated"; "required": false; }; "snoozeMs": { "alias": "snoozeMs"; "required": false; }; "autoOpenSettingsOnOutdated": { "alias": "autoOpenSettingsOnOutdated"; "required": false; }; "readonlyModeGlobal": { "alias": "readonlyModeGlobal"; "required": false; }; "disabledModeGlobal": { "alias": "disabledModeGlobal"; "required": false; }; "presentationModeGlobal": { "alias": "presentationModeGlobal"; "required": false; }; "visibleGlobal": { "alias": "visibleGlobal"; "required": false; }; "fieldIconPolicy": { "alias": "fieldIconPolicy"; "required": false; }; "domainRules": { "alias": "domainRules"; "required": false; }; "customEndpoints": { "alias": "customEndpoints"; "required": false; }; }, { "formSubmit": "formSubmit"; "formCancel": "formCancel"; "formReset": "formReset"; "configChange": "configChange"; "configPatchChange": "configPatchChange"; "formReady": "formReady"; "valueChange": "valueChange"; "syncCompleted": "syncCompleted"; "initializationError": "initializationError"; "loadingStateChange": "loadingStateChange"; "enableCustomizationChange": "enableCustomizationChange"; "customAction": "customAction"; "actionConfirmation": "actionConfirmation"; "schemaStatusChange": "schemaStatusChange"; "fieldRenderError": "fieldRenderError"; "ruleDiagnosticsChange": "ruleDiagnosticsChange"; }, never, never, true, never>;
|
|
1372
1378
|
}
|
|
1373
1379
|
|