@praxisui/manual-form 8.0.0-beta.7 → 8.0.0-beta.71
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 +30 -1
- package/fesm2022/praxisui-manual-form.mjs +1150 -97
- package/package.json +17 -10
- package/{index.d.ts → types/praxisui-manual-form.d.ts} +47 -3
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ensureIds, DynamicFormService, ASYNC_CONFIG_STORAGE, RULE_PROPERTY_SCHEMA, deepMerge, resolveControlTypeAlias, FieldControlType, normalizeControlTypeKey, FormHooksRegistry, ComponentKeyService, FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, DEFAULT_FIELD_SELECTOR_CONTROL_TYPE_MAP, FieldSelectorRegistry, providePraxisI18n, PraxisI18nService, API_URL } from '@praxisui/core';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { inject, Optional, Inject, Injectable, input, output, ChangeDetectionStrategy, Component, Input, InjectionToken, isDevMode, EventEmitter, HostListener, ViewChild, Output, ChangeDetectorRef, DestroyRef, PLATFORM_ID, effect, ContentChildren, signal, computed, Directive } from '@angular/core';
|
|
4
|
-
import { BehaviorSubject, debounceTime, fromEvent, of } from 'rxjs';
|
|
4
|
+
import { BehaviorSubject, firstValueFrom, debounceTime, fromEvent, of } from 'rxjs';
|
|
5
5
|
import { take } from 'rxjs/operators';
|
|
6
|
-
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
|
7
6
|
import { ActivatedRoute } from '@angular/router';
|
|
8
|
-
import {
|
|
7
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
8
|
+
import { BaseAiAdapter, shouldRoutePromptToGovernedDecision, AiBackendApiService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnOrchestratorService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
|
|
9
9
|
import * as i1 from '@angular/forms';
|
|
10
10
|
import { FormGroupDirective, FormGroup, FormControl, Validators, ReactiveFormsModule, FormControlName, ControlContainer, FormsModule } from '@angular/forms';
|
|
11
11
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
@@ -361,10 +361,10 @@ class ManualFormInstanceFactory {
|
|
|
361
361
|
}
|
|
362
362
|
return instance;
|
|
363
363
|
}
|
|
364
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
365
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
364
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormInstanceFactory, deps: [{ token: ASYNC_CONFIG_STORAGE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
365
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormInstanceFactory, providedIn: 'root' });
|
|
366
366
|
}
|
|
367
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
367
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormInstanceFactory, decorators: [{
|
|
368
368
|
type: Injectable,
|
|
369
369
|
args: [{ providedIn: 'root' }]
|
|
370
370
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
@@ -384,13 +384,13 @@ function buildStorageKey(formId, options = {}) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
class ManualFormHeaderComponent {
|
|
387
|
-
instance = input(...(ngDevMode ? [undefined, { debugName: "instance" }] : []));
|
|
388
|
-
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
|
|
389
|
-
description = input(...(ngDevMode ? [undefined, { debugName: "description" }] : []));
|
|
390
|
-
saveLabel = input('Salvar customizações', ...(ngDevMode ? [{ debugName: "saveLabel" }] : []));
|
|
391
|
-
resetLabel = input('Restaurar padrão', ...(ngDevMode ? [{ debugName: "resetLabel" }] : []));
|
|
392
|
-
enableCustomization = input(false, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : []));
|
|
393
|
-
editFormLabel = input('Editar formulário', ...(ngDevMode ? [{ debugName: "editFormLabel" }] : []));
|
|
387
|
+
instance = input(...(ngDevMode ? [undefined, { debugName: "instance" }] : /* istanbul ignore next */ []));
|
|
388
|
+
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
|
|
389
|
+
description = input(...(ngDevMode ? [undefined, { debugName: "description" }] : /* istanbul ignore next */ []));
|
|
390
|
+
saveLabel = input('Salvar customizações', ...(ngDevMode ? [{ debugName: "saveLabel" }] : /* istanbul ignore next */ []));
|
|
391
|
+
resetLabel = input('Restaurar padrão', ...(ngDevMode ? [{ debugName: "resetLabel" }] : /* istanbul ignore next */ []));
|
|
392
|
+
enableCustomization = input(false, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : /* istanbul ignore next */ []));
|
|
393
|
+
editFormLabel = input('Editar formulário', ...(ngDevMode ? [{ debugName: "editFormLabel" }] : /* istanbul ignore next */ []));
|
|
394
394
|
save = output();
|
|
395
395
|
reset = output();
|
|
396
396
|
editForm = output();
|
|
@@ -413,8 +413,8 @@ class ManualFormHeaderComponent {
|
|
|
413
413
|
this.firstSection?.description ||
|
|
414
414
|
undefined);
|
|
415
415
|
}
|
|
416
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
417
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
416
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
417
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormHeaderComponent, isStandalone: true, selector: "praxis-manual-form-header", inputs: { instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, saveLabel: { classPropertyName: "saveLabel", publicName: "saveLabel", isSignal: true, isRequired: false, transformFunction: null }, resetLabel: { classPropertyName: "resetLabel", publicName: "resetLabel", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, editFormLabel: { classPropertyName: "editFormLabel", publicName: "editFormLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { save: "save", reset: "reset", editForm: "editForm" }, ngImport: i0, template: `
|
|
418
418
|
<header class="pdx-manual-form__header">
|
|
419
419
|
<div class="pdx-manual-form__title">
|
|
420
420
|
<h2>{{ displayTitle }}</h2>
|
|
@@ -432,11 +432,11 @@ class ManualFormHeaderComponent {
|
|
|
432
432
|
<button type="button" class="pdx-btn pdx-btn--primary" (click)="save.emit()" [attr.aria-label]="saveLabel()">{{ saveLabel() }}</button>
|
|
433
433
|
</div>
|
|
434
434
|
</header>
|
|
435
|
-
`, isInline: true, styles: [":host{display:block}.pdx-manual-form__header{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-bottom:1.5rem}.pdx-manual-form__title h2{margin:0;font-size:1.25rem;font-weight:600;line-height:1.3}.pdx-manual-form__subtitle{margin:.25rem 0 0;color:var(--md-sys-color-on-surface-variant)}.pdx-manual-form__header-actions{display:flex;gap:.5rem;flex-wrap:wrap}.pdx-btn{min-height:36px;padding:0 14px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-btn--ghost{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.pdx-btn--primary{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-btn--primary:hover{background:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}\n"],
|
|
435
|
+
`, isInline: true, styles: [":host{display:block}.pdx-manual-form__header{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-bottom:1.5rem}.pdx-manual-form__title h2{margin:0;font-size:1.25rem;font-weight:600;line-height:1.3}.pdx-manual-form__subtitle{margin:.25rem 0 0;color:var(--md-sys-color-on-surface-variant)}.pdx-manual-form__header-actions{display:flex;gap:.5rem;flex-wrap:wrap}.pdx-btn{min-height:36px;padding:0 14px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-btn--ghost{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.pdx-btn--primary{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}.pdx-btn--primary:hover{background:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
436
436
|
}
|
|
437
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
437
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormHeaderComponent, decorators: [{
|
|
438
438
|
type: Component,
|
|
439
|
-
args: [{ selector: 'praxis-manual-form-header', standalone: true, imports: [
|
|
439
|
+
args: [{ selector: 'praxis-manual-form-header', standalone: true, imports: [], template: `
|
|
440
440
|
<header class="pdx-manual-form__header">
|
|
441
441
|
<div class="pdx-manual-form__title">
|
|
442
442
|
<h2>{{ displayTitle }}</h2>
|
|
@@ -458,7 +458,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
458
458
|
}], propDecorators: { instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], saveLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveLabel", required: false }] }], resetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetLabel", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], editFormLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "editFormLabel", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], reset: [{ type: i0.Output, args: ["reset"] }], editForm: [{ type: i0.Output, args: ["editForm"] }] } });
|
|
459
459
|
|
|
460
460
|
class ManualFormActionsComponent {
|
|
461
|
-
actions = input(...(ngDevMode ? [undefined, { debugName: "actions" }] : []));
|
|
461
|
+
actions = input(...(ngDevMode ? [undefined, { debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
462
462
|
trackByFn = null;
|
|
463
463
|
actionClick = output();
|
|
464
464
|
isVisible(action) {
|
|
@@ -472,8 +472,8 @@ class ManualFormActionsComponent {
|
|
|
472
472
|
this.actionClick.emit(kind);
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
476
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
475
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
476
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormActionsComponent, isStandalone: true, selector: "praxis-manual-form-actions", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, trackByFn: { classPropertyName: "trackByFn", publicName: "trackByFn", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: `
|
|
477
477
|
@if (actions(); as layout) {
|
|
478
478
|
<footer class="pdx-manual-form__actions">
|
|
479
479
|
<div class="pdx-manual-form__actions-secondary">
|
|
@@ -510,11 +510,11 @@ class ManualFormActionsComponent {
|
|
|
510
510
|
</div>
|
|
511
511
|
</footer>
|
|
512
512
|
}
|
|
513
|
-
`, isInline: true, styles: [":host{display:block}.pdx-manual-form__actions{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-top:2rem;flex-wrap:wrap}.pdx-manual-form__actions-secondary,.pdx-manual-form__actions-primary{display:flex;gap:.5rem}.pdx-btn{min-height:36px;padding:0 14px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-btn--ghost{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.pdx-btn--primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);border-color:var(--md-sys-color-primary)}.pdx-btn--primary:hover{background:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}\n"],
|
|
513
|
+
`, isInline: true, styles: [":host{display:block}.pdx-manual-form__actions{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-top:2rem;flex-wrap:wrap}.pdx-manual-form__actions-secondary,.pdx-manual-form__actions-primary{display:flex;gap:.5rem}.pdx-btn{min-height:36px;padding:0 14px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.pdx-btn:hover{background:var(--md-sys-color-surface-container)}.pdx-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-btn:disabled{opacity:.6;cursor:not-allowed}.pdx-btn--ghost{background:transparent;border-color:var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.pdx-btn--primary{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);border-color:var(--md-sys-color-primary)}.pdx-btn--primary:hover{background:var(--md-sys-color-primary-container);border-color:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
514
514
|
}
|
|
515
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
515
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormActionsComponent, decorators: [{
|
|
516
516
|
type: Component,
|
|
517
|
-
args: [{ selector: 'praxis-manual-form-actions', standalone: true, imports: [
|
|
517
|
+
args: [{ selector: 'praxis-manual-form-actions', standalone: true, imports: [], template: `
|
|
518
518
|
@if (actions(); as layout) {
|
|
519
519
|
<footer class="pdx-manual-form__actions">
|
|
520
520
|
<div class="pdx-manual-form__actions-secondary">
|
|
@@ -576,7 +576,7 @@ const ENUMS = {
|
|
|
576
576
|
headerAlign: ['start', 'center'],
|
|
577
577
|
schemaType: ['response', 'request'],
|
|
578
578
|
customizationSource: ['user', 'server', 'system'],
|
|
579
|
-
formRuleTargetType: ['field', 'section', 'action', 'row', 'column'],
|
|
579
|
+
formRuleTargetType: ['field', 'section', 'action', 'row', 'column', 'visualBlock'],
|
|
580
580
|
formRuleContext: ['visibility', 'readOnly', 'style', 'validation', 'notification'],
|
|
581
581
|
mode: ['create', 'edit', 'view'],
|
|
582
582
|
schemaSource: ['resource', 'filter'],
|
|
@@ -1083,6 +1083,8 @@ const MANUAL_FORM_AI_CAPABILITIES = {
|
|
|
1083
1083
|
class ManualFormAiAdapter extends BaseAiAdapter {
|
|
1084
1084
|
host;
|
|
1085
1085
|
componentName = 'Manual Form';
|
|
1086
|
+
componentId = 'praxis-manual-form';
|
|
1087
|
+
componentType = 'form';
|
|
1086
1088
|
constructor(host) {
|
|
1087
1089
|
super();
|
|
1088
1090
|
this.host = host;
|
|
@@ -1105,6 +1107,48 @@ class ManualFormAiAdapter extends BaseAiAdapter {
|
|
|
1105
1107
|
dirty: form?.dirty ?? false,
|
|
1106
1108
|
};
|
|
1107
1109
|
}
|
|
1110
|
+
getDataProfile() {
|
|
1111
|
+
const config = this.host.instance?.currentConfig;
|
|
1112
|
+
return {
|
|
1113
|
+
formId: this.safeFormId(),
|
|
1114
|
+
sectionCount: config?.sections?.length ?? 0,
|
|
1115
|
+
fieldCount: config?.fieldMetadata?.length ?? 0,
|
|
1116
|
+
actionCount: [
|
|
1117
|
+
config?.actions?.submit,
|
|
1118
|
+
config?.actions?.cancel,
|
|
1119
|
+
config?.actions?.reset,
|
|
1120
|
+
...(config?.actions?.custom ?? []),
|
|
1121
|
+
].filter(Boolean).length,
|
|
1122
|
+
hasPersistence: !!this.host.persistenceOptions(),
|
|
1123
|
+
autoSave: !!this.host.enableAutoSave(),
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
getSchemaFields() {
|
|
1127
|
+
return (this.host.instance?.currentConfig?.fieldMetadata ?? [])
|
|
1128
|
+
.map((field) => ({
|
|
1129
|
+
name: field.name,
|
|
1130
|
+
label: field.label,
|
|
1131
|
+
type: field.type,
|
|
1132
|
+
required: !!(field.required || field.validators?.required),
|
|
1133
|
+
readonly: !!field.readonly,
|
|
1134
|
+
hidden: !!field.hidden,
|
|
1135
|
+
}))
|
|
1136
|
+
.filter((field) => typeof field.name === 'string' && !!field.name.trim());
|
|
1137
|
+
}
|
|
1138
|
+
getAuthoringContext() {
|
|
1139
|
+
return {
|
|
1140
|
+
authoringManifestRef: 'PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST',
|
|
1141
|
+
runtimeAuthoringPolicy: {
|
|
1142
|
+
mode: 'agentic-authoring',
|
|
1143
|
+
enableCustomization: !!this.host.enableCustomization(),
|
|
1144
|
+
canApplyLocalPatch: false,
|
|
1145
|
+
reason: 'praxis-manual-form ainda exige componentEditPlan manifest-backed antes de aplicar patch local pelo copiloto.',
|
|
1146
|
+
},
|
|
1147
|
+
domainCatalog: {
|
|
1148
|
+
recommendedAuthoringFlow: 'component_authoring',
|
|
1149
|
+
},
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1108
1152
|
createSnapshot() {
|
|
1109
1153
|
return this.getCurrentConfig();
|
|
1110
1154
|
}
|
|
@@ -1178,6 +1222,336 @@ class ManualFormAiAdapter extends BaseAiAdapter {
|
|
|
1178
1222
|
}
|
|
1179
1223
|
}
|
|
1180
1224
|
|
|
1225
|
+
class ManualFormAgenticAuthoringTurnFlow {
|
|
1226
|
+
adapter;
|
|
1227
|
+
aiApi;
|
|
1228
|
+
mode = 'agentic-authoring';
|
|
1229
|
+
constructor(adapter, aiApi) {
|
|
1230
|
+
this.adapter = adapter;
|
|
1231
|
+
this.aiApi = aiApi;
|
|
1232
|
+
}
|
|
1233
|
+
async submit(request) {
|
|
1234
|
+
const prompt = (request.prompt ?? '').trim();
|
|
1235
|
+
if (!prompt) {
|
|
1236
|
+
return {
|
|
1237
|
+
state: 'listening',
|
|
1238
|
+
phase: 'capture',
|
|
1239
|
+
statusText: '',
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
const componentId = this.adapter.componentId || request.componentId || 'praxis-manual-form';
|
|
1243
|
+
const componentType = this.adapter.componentType || request.componentType || 'form';
|
|
1244
|
+
const currentState = this.toAiJsonObject(this.adapter.getCurrentConfig());
|
|
1245
|
+
const dataProfile = this.optionalJsonObject(this.adapter.getDataProfile?.());
|
|
1246
|
+
const runtimeState = this.optionalJsonObject(this.adapter.getRuntimeState?.());
|
|
1247
|
+
const schemaFields = this.adapter.getSchemaFields?.()
|
|
1248
|
+
?.map((field) => this.toAiJsonObject(field))
|
|
1249
|
+
.filter((field) => Object.keys(field).length > 0);
|
|
1250
|
+
const contextHints = this.mergeJsonObjects(this.optionalJsonObject(this.adapter.getAuthoringContext?.()), this.optionalJsonObject(request.action?.contextHints));
|
|
1251
|
+
if (this.shouldRouteToGovernedDecision(prompt, contextHints)) {
|
|
1252
|
+
return this.toGovernedDecisionHandoff(prompt, request);
|
|
1253
|
+
}
|
|
1254
|
+
const response = await firstValueFrom(this.aiApi.getPatch({
|
|
1255
|
+
componentId,
|
|
1256
|
+
componentType,
|
|
1257
|
+
userPrompt: prompt,
|
|
1258
|
+
sessionId: request.sessionId,
|
|
1259
|
+
clientTurnId: request.clientTurnId,
|
|
1260
|
+
messages: this.toChatMessages(request.messages, prompt),
|
|
1261
|
+
currentState,
|
|
1262
|
+
currentStateDigest: this.buildCurrentStateDigest(dataProfile),
|
|
1263
|
+
uiContextRef: {
|
|
1264
|
+
componentId,
|
|
1265
|
+
componentType,
|
|
1266
|
+
},
|
|
1267
|
+
...(dataProfile ? { dataProfile } : {}),
|
|
1268
|
+
...(runtimeState ? { runtimeState } : {}),
|
|
1269
|
+
...(schemaFields?.length ? { schemaFields } : {}),
|
|
1270
|
+
...(contextHints ? { contextHints } : {}),
|
|
1271
|
+
}));
|
|
1272
|
+
return this.toTurnResult(this.compileAdapterResponse(response), request);
|
|
1273
|
+
}
|
|
1274
|
+
async apply(_request) {
|
|
1275
|
+
return {
|
|
1276
|
+
state: 'error',
|
|
1277
|
+
phase: 'apply',
|
|
1278
|
+
assistantMessage: 'O formulario manual ainda exige componentEditPlan validado pelo manifesto antes de aplicar mudancas locais.',
|
|
1279
|
+
errorText: 'Aplicacao local bloqueada ate existir compilacao manifest-backed para praxis-manual-form.',
|
|
1280
|
+
canApply: false,
|
|
1281
|
+
pendingPatch: null,
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
cancel() {
|
|
1285
|
+
return Promise.resolve({
|
|
1286
|
+
state: 'listening',
|
|
1287
|
+
phase: 'capture',
|
|
1288
|
+
assistantMessage: 'Solicitacao cancelada.',
|
|
1289
|
+
statusText: '',
|
|
1290
|
+
canApply: false,
|
|
1291
|
+
pendingPatch: null,
|
|
1292
|
+
pendingClarification: null,
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
retry(request) {
|
|
1296
|
+
const lastPrompt = [...(request.messages ?? [])].reverse()
|
|
1297
|
+
.find((message) => message.role === 'user')?.text;
|
|
1298
|
+
return this.submit({
|
|
1299
|
+
...request,
|
|
1300
|
+
prompt: lastPrompt ?? request.prompt,
|
|
1301
|
+
action: { kind: 'retry' },
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
toTurnResult(response, request) {
|
|
1305
|
+
if (!response) {
|
|
1306
|
+
return {
|
|
1307
|
+
state: 'error',
|
|
1308
|
+
phase: 'capture',
|
|
1309
|
+
assistantMessage: 'Resposta vazia da IA.',
|
|
1310
|
+
errorText: 'Resposta vazia da IA.',
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
if (response.type === 'clarification') {
|
|
1314
|
+
return {
|
|
1315
|
+
state: 'clarification',
|
|
1316
|
+
phase: 'clarify',
|
|
1317
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1318
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1319
|
+
assistantMessage: response.message || 'Preciso de mais detalhes para continuar.',
|
|
1320
|
+
clarificationQuestions: this.toClarificationQuestions(response),
|
|
1321
|
+
quickReplies: this.toQuickReplies(response),
|
|
1322
|
+
canApply: false,
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
if (response.type === 'info') {
|
|
1326
|
+
const message = response.message || response.explanation || 'Informacao gerada.';
|
|
1327
|
+
return {
|
|
1328
|
+
state: 'success',
|
|
1329
|
+
phase: 'summarize',
|
|
1330
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1331
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1332
|
+
assistantMessage: message,
|
|
1333
|
+
statusText: message,
|
|
1334
|
+
canApply: false,
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
if (response.type === 'error') {
|
|
1338
|
+
const message = response.message || 'Falha ao gerar alteracao de formulario manual.';
|
|
1339
|
+
return {
|
|
1340
|
+
state: 'error',
|
|
1341
|
+
phase: 'capture',
|
|
1342
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1343
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1344
|
+
assistantMessage: message,
|
|
1345
|
+
errorText: message,
|
|
1346
|
+
diagnostics: response.warnings?.length ? { warnings: response.warnings } : undefined,
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
if (response.patch && Object.keys(response.patch).length > 0) {
|
|
1350
|
+
return {
|
|
1351
|
+
state: 'error',
|
|
1352
|
+
phase: 'review',
|
|
1353
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1354
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1355
|
+
assistantMessage: 'O formulario manual rejeitou patch livre. Gere um componentEditPlan validado pelo PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST antes de propor alteracao local.',
|
|
1356
|
+
errorText: 'Patch livre de formulario manual rejeitado.',
|
|
1357
|
+
canApply: false,
|
|
1358
|
+
pendingPatch: null,
|
|
1359
|
+
diagnostics: {
|
|
1360
|
+
warnings: [
|
|
1361
|
+
'free-manual-form-patch-rejected',
|
|
1362
|
+
'Use componentEditPlan validado contra PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST.',
|
|
1363
|
+
],
|
|
1364
|
+
},
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
return {
|
|
1368
|
+
state: 'success',
|
|
1369
|
+
phase: 'summarize',
|
|
1370
|
+
sessionId: response.sessionId ?? request.sessionId,
|
|
1371
|
+
observationId: response.observationId ?? request.observationId ?? null,
|
|
1372
|
+
assistantMessage: response.message || response.explanation || 'Nenhuma alteracao necessaria.',
|
|
1373
|
+
statusText: response.message || response.explanation || 'Nenhuma alteracao necessaria.',
|
|
1374
|
+
canApply: false,
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
compileAdapterResponse(response) {
|
|
1378
|
+
const compiled = this.adapter.compileAiResponse?.(response);
|
|
1379
|
+
if (!compiled) {
|
|
1380
|
+
return response;
|
|
1381
|
+
}
|
|
1382
|
+
if (compiled.type === 'error') {
|
|
1383
|
+
return {
|
|
1384
|
+
type: 'error',
|
|
1385
|
+
message: compiled.message || 'O componentEditPlan do formulario manual nao passou na validacao de capacidades.',
|
|
1386
|
+
warnings: compiled.warnings,
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
const warnings = [
|
|
1390
|
+
...(response.warnings ?? []),
|
|
1391
|
+
...(compiled.warnings ?? []),
|
|
1392
|
+
];
|
|
1393
|
+
return {
|
|
1394
|
+
...response,
|
|
1395
|
+
...compiled,
|
|
1396
|
+
patch: compiled.patch,
|
|
1397
|
+
warnings: warnings.length ? warnings : undefined,
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
toChatMessages(messages, prompt) {
|
|
1401
|
+
const supported = (messages ?? [])
|
|
1402
|
+
.filter((message) => message.role === 'user' || message.role === 'assistant' || message.role === 'system')
|
|
1403
|
+
.map((message) => ({
|
|
1404
|
+
role: message.role,
|
|
1405
|
+
content: message.text,
|
|
1406
|
+
}))
|
|
1407
|
+
.filter((message) => message.content.trim().length > 0);
|
|
1408
|
+
return supported.length ? supported : [{ role: 'user', content: prompt }];
|
|
1409
|
+
}
|
|
1410
|
+
toClarificationQuestions(response) {
|
|
1411
|
+
const labels = response.questions?.length
|
|
1412
|
+
? response.questions
|
|
1413
|
+
: response.message
|
|
1414
|
+
? [response.message]
|
|
1415
|
+
: ['Qual ajuste voce quer aplicar no formulario manual?'];
|
|
1416
|
+
const options = this.toQuickReplies(response).map((reply) => ({
|
|
1417
|
+
id: reply.id,
|
|
1418
|
+
label: reply.label,
|
|
1419
|
+
value: reply.prompt,
|
|
1420
|
+
description: reply.description ?? undefined,
|
|
1421
|
+
contextHints: reply.contextHints ? { ...reply.contextHints } : undefined,
|
|
1422
|
+
}));
|
|
1423
|
+
return labels.map((label, index) => ({
|
|
1424
|
+
id: `manual-form-clarification-${index + 1}`,
|
|
1425
|
+
type: options.length ? 'single-choice' : 'text',
|
|
1426
|
+
label,
|
|
1427
|
+
allowCustom: true,
|
|
1428
|
+
options,
|
|
1429
|
+
}));
|
|
1430
|
+
}
|
|
1431
|
+
toQuickReplies(response) {
|
|
1432
|
+
const payloads = response.optionPayloads ?? [];
|
|
1433
|
+
if (payloads.length) {
|
|
1434
|
+
return payloads
|
|
1435
|
+
.map((option, index) => {
|
|
1436
|
+
const label = option.label?.trim() || option.value?.trim() || `Opcao ${index + 1}`;
|
|
1437
|
+
const prompt = option.value?.trim() || option.example?.trim() || label;
|
|
1438
|
+
return {
|
|
1439
|
+
id: `option-${index + 1}`,
|
|
1440
|
+
label,
|
|
1441
|
+
prompt,
|
|
1442
|
+
kind: 'clarification-option',
|
|
1443
|
+
description: option.example?.trim() || undefined,
|
|
1444
|
+
contextHints: this.optionalJsonObject(option.contextHints),
|
|
1445
|
+
};
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
return (response.options ?? [])
|
|
1449
|
+
.filter((option) => !!option?.trim())
|
|
1450
|
+
.map((option, index) => ({
|
|
1451
|
+
id: `option-${index + 1}`,
|
|
1452
|
+
label: option.trim(),
|
|
1453
|
+
prompt: option.trim(),
|
|
1454
|
+
kind: 'clarification-option',
|
|
1455
|
+
}));
|
|
1456
|
+
}
|
|
1457
|
+
buildCurrentStateDigest(dataProfile) {
|
|
1458
|
+
const fieldCount = typeof dataProfile?.['fieldCount'] === 'number' ? dataProfile['fieldCount'] : undefined;
|
|
1459
|
+
return fieldCount !== undefined ? { rowCount: fieldCount } : {};
|
|
1460
|
+
}
|
|
1461
|
+
shouldRouteToGovernedDecision(prompt, contextHints) {
|
|
1462
|
+
return shouldRoutePromptToGovernedDecision(prompt, contextHints);
|
|
1463
|
+
}
|
|
1464
|
+
toGovernedDecisionHandoff(prompt, request) {
|
|
1465
|
+
const message = 'Esse pedido parece alterar uma decisao de negocio compartilhada. O formulario manual pode localizar campos e experiencia afetada, mas a regra deve seguir pelo fluxo governado de domain-rules antes de qualquer materializacao runtime.';
|
|
1466
|
+
return {
|
|
1467
|
+
state: 'clarification',
|
|
1468
|
+
phase: 'clarify',
|
|
1469
|
+
sessionId: request.sessionId,
|
|
1470
|
+
assistantMessage: message,
|
|
1471
|
+
statusText: 'Handoff governado necessario.',
|
|
1472
|
+
canApply: false,
|
|
1473
|
+
quickReplies: [
|
|
1474
|
+
{
|
|
1475
|
+
id: 'shared-rule-handoff',
|
|
1476
|
+
label: 'Continuar como regra governada',
|
|
1477
|
+
prompt,
|
|
1478
|
+
kind: 'shared-rule-handoff',
|
|
1479
|
+
description: 'Criar intake de domain-rules em vez de aplicar patch local no formulario.',
|
|
1480
|
+
icon: 'rule',
|
|
1481
|
+
tone: 'warning',
|
|
1482
|
+
contextHints: {
|
|
1483
|
+
flowId: 'shared_rule_authoring',
|
|
1484
|
+
source: 'praxis-manual-form',
|
|
1485
|
+
recommendedAction: 'domain-rules/intake',
|
|
1486
|
+
},
|
|
1487
|
+
},
|
|
1488
|
+
],
|
|
1489
|
+
clarificationQuestions: [
|
|
1490
|
+
{
|
|
1491
|
+
id: 'manual-form-governed-rule-confirmation',
|
|
1492
|
+
type: 'confirm',
|
|
1493
|
+
label: 'Deseja continuar pelo fluxo governado de regras compartilhadas?',
|
|
1494
|
+
description: 'Esse caminho permite intake, simulacao, aprovacao/publicacao, materializacao e validacao de enforcement.',
|
|
1495
|
+
required: true,
|
|
1496
|
+
options: [
|
|
1497
|
+
{
|
|
1498
|
+
id: 'shared-rule-handoff',
|
|
1499
|
+
label: 'Sim, continuar governado',
|
|
1500
|
+
value: prompt,
|
|
1501
|
+
description: 'Nao aplicar como patch local do formulario.',
|
|
1502
|
+
contextHints: {
|
|
1503
|
+
flowId: 'shared_rule_authoring',
|
|
1504
|
+
source: 'praxis-manual-form',
|
|
1505
|
+
},
|
|
1506
|
+
},
|
|
1507
|
+
],
|
|
1508
|
+
},
|
|
1509
|
+
],
|
|
1510
|
+
diagnostics: {
|
|
1511
|
+
governedDecisionHandoff: {
|
|
1512
|
+
flowId: 'shared_rule_authoring',
|
|
1513
|
+
sourcePrompt: prompt,
|
|
1514
|
+
sourceComponent: 'praxis-manual-form',
|
|
1515
|
+
},
|
|
1516
|
+
},
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
optionalJsonObject(value) {
|
|
1520
|
+
if (value === undefined || value === null) {
|
|
1521
|
+
return undefined;
|
|
1522
|
+
}
|
|
1523
|
+
const object = this.toAiJsonObject(value);
|
|
1524
|
+
return Object.keys(object).length ? object : undefined;
|
|
1525
|
+
}
|
|
1526
|
+
mergeJsonObjects(base, overlay) {
|
|
1527
|
+
if (!base)
|
|
1528
|
+
return overlay;
|
|
1529
|
+
if (!overlay)
|
|
1530
|
+
return base;
|
|
1531
|
+
return {
|
|
1532
|
+
...base,
|
|
1533
|
+
...overlay,
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1536
|
+
toAiJsonObject(value) {
|
|
1537
|
+
const record = this.toRecord(value);
|
|
1538
|
+
if (!record) {
|
|
1539
|
+
return {};
|
|
1540
|
+
}
|
|
1541
|
+
try {
|
|
1542
|
+
return JSON.parse(JSON.stringify(record));
|
|
1543
|
+
}
|
|
1544
|
+
catch {
|
|
1545
|
+
return {};
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
toRecord(value) {
|
|
1549
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
1550
|
+
? value
|
|
1551
|
+
: null;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1181
1555
|
const MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE = new InjectionToken('MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE');
|
|
1182
1556
|
const MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE = new InjectionToken('MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE');
|
|
1183
1557
|
|
|
@@ -1363,10 +1737,10 @@ class ManualFieldMetadataBridgeService {
|
|
|
1363
1737
|
bindComponent(instance, fieldName, componentInstance) {
|
|
1364
1738
|
instance.bindComponent(fieldName, componentInstance);
|
|
1365
1739
|
}
|
|
1366
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1367
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1740
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldMetadataBridgeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1741
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldMetadataBridgeService, providedIn: 'root' });
|
|
1368
1742
|
}
|
|
1369
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1743
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldMetadataBridgeService, decorators: [{
|
|
1370
1744
|
type: Injectable,
|
|
1371
1745
|
args: [{ providedIn: 'root' }]
|
|
1372
1746
|
}] });
|
|
@@ -1402,10 +1776,10 @@ class ManualFieldKeyService {
|
|
|
1402
1776
|
}
|
|
1403
1777
|
return { status: 'missing' };
|
|
1404
1778
|
}
|
|
1405
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1406
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1779
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldKeyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1780
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldKeyService, providedIn: 'root' });
|
|
1407
1781
|
}
|
|
1408
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1782
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldKeyService, decorators: [{
|
|
1409
1783
|
type: Injectable,
|
|
1410
1784
|
args: [{ providedIn: 'root' }]
|
|
1411
1785
|
}] });
|
|
@@ -1436,8 +1810,8 @@ class ManualFieldToolbarComponent {
|
|
|
1436
1810
|
this.requestClose.emit();
|
|
1437
1811
|
}
|
|
1438
1812
|
}
|
|
1439
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1440
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
1813
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1814
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: ManualFieldToolbarComponent, isStandalone: true, selector: "praxis-manual-field-toolbar", inputs: { metadata: "metadata" }, outputs: { toggleRequired: "toggleRequired", toggleReadonly: "toggleReadonly", toggleHidden: "toggleHidden", toggleDisabled: "toggleDisabled", openEditor: "openEditor", requestClose: "requestClose" }, host: { listeners: { "keydown": "onKeydown($event)" } }, viewQueries: [{ propertyName: "firstAction", first: true, predicate: ["firstAction"], descendants: true, static: true }], ngImport: i0, template: `
|
|
1441
1815
|
<div
|
|
1442
1816
|
class="pdx-manual-field-toolbar"
|
|
1443
1817
|
role="toolbar"
|
|
@@ -1511,11 +1885,11 @@ class ManualFieldToolbarComponent {
|
|
|
1511
1885
|
<span class="material-symbols-outlined">close</span>
|
|
1512
1886
|
</button>
|
|
1513
1887
|
</div>
|
|
1514
|
-
`, isInline: true, styles: [":host{display:block;pointer-events:auto;font-family:inherit}.pdx-manual-field-toolbar{display:inline-flex;align-items:center;gap:6px;padding:6px;border-radius:12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level3);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}.toolbar-btn{appearance:none;border:0;background:transparent;color:var(--md-sys-color-on-surface);display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:10px;cursor:pointer;transition:background-color .12s ease,transform .12s ease}.toolbar-btn:hover{background:var(--md-sys-color-primary-container)}.toolbar-btn:active{transform:scale(.97)}.toolbar-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.toolbar-btn--accent{background:var(--md-sys-color-primary-container)}.toolbar-btn--ghost{opacity:.7}.material-symbols-outlined{font-size:18px;line-height:18px}.toolbar-icon{font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 20}.toolbar-icon--filled{font-variation-settings:\"FILL\" 1,\"wght\" 600,\"GRAD\" 0,\"opsz\" 20}\n"]
|
|
1888
|
+
`, isInline: true, styles: [":host{display:block;pointer-events:auto;font-family:inherit}.pdx-manual-field-toolbar{display:inline-flex;align-items:center;gap:6px;padding:6px;border-radius:12px;background:var(--md-sys-color-surface-container-low);border:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level3);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}.toolbar-btn{appearance:none;border:0;background:transparent;color:var(--md-sys-color-on-surface);display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:10px;cursor:pointer;transition:background-color .12s ease,transform .12s ease}.toolbar-btn:hover{background:var(--md-sys-color-primary-container)}.toolbar-btn:active{transform:scale(.97)}.toolbar-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.toolbar-btn--accent{background:var(--md-sys-color-primary-container)}.toolbar-btn--ghost{opacity:.7}.material-symbols-outlined{font-size:18px;line-height:18px}.toolbar-icon{font-variation-settings:\"FILL\" 0,\"wght\" 400,\"GRAD\" 0,\"opsz\" 20}.toolbar-icon--filled{font-variation-settings:\"FILL\" 1,\"wght\" 600,\"GRAD\" 0,\"opsz\" 20}\n"] });
|
|
1515
1889
|
}
|
|
1516
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1890
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldToolbarComponent, decorators: [{
|
|
1517
1891
|
type: Component,
|
|
1518
|
-
args: [{ selector: 'praxis-manual-field-toolbar', standalone: true, imports: [
|
|
1892
|
+
args: [{ selector: 'praxis-manual-field-toolbar', standalone: true, imports: [], template: `
|
|
1519
1893
|
<div
|
|
1520
1894
|
class="pdx-manual-field-toolbar"
|
|
1521
1895
|
role="toolbar"
|
|
@@ -1629,6 +2003,17 @@ class ManualFormComponent {
|
|
|
1629
2003
|
catch {
|
|
1630
2004
|
return undefined;
|
|
1631
2005
|
} })();
|
|
2006
|
+
aiApi = inject(AiBackendApiService);
|
|
2007
|
+
assistantSessions = inject(PraxisAssistantSessionRegistryService);
|
|
2008
|
+
aiTurnOrchestrator = inject(PraxisAssistantTurnOrchestratorService);
|
|
2009
|
+
aiAssistantSessionEffect = effect(() => {
|
|
2010
|
+
const session = this.assistantSessions.activeSession();
|
|
2011
|
+
if (!session || session.id !== this.resolveAiAssistantSessionId())
|
|
2012
|
+
return;
|
|
2013
|
+
if (!this.aiAssistantOpen) {
|
|
2014
|
+
this.openAiAssistantFromSession(session);
|
|
2015
|
+
}
|
|
2016
|
+
}, ...(ngDevMode ? [{ debugName: "aiAssistantSessionEffect" }] : /* istanbul ignore next */ []));
|
|
1632
2017
|
warnedMissingId = false;
|
|
1633
2018
|
disableSelectorDefaults = inject(FIELD_SELECTOR_REGISTRY_DISABLE_DEFAULTS, { optional: true }) ?? false;
|
|
1634
2019
|
selectorToControlType = inject(MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, { optional: true }) ??
|
|
@@ -1643,22 +2028,22 @@ class ManualFormComponent {
|
|
|
1643
2028
|
toolbarActionSubscriptions = [];
|
|
1644
2029
|
metadataSubscription;
|
|
1645
2030
|
outsideClickSubscription;
|
|
1646
|
-
formId = input.required(...(ngDevMode ? [{ debugName: "formId" }] : []));
|
|
1647
|
-
formTitle = input(...(ngDevMode ? [undefined, { debugName: "formTitle" }] : []));
|
|
1648
|
-
formDescription = input(...(ngDevMode ? [undefined, { debugName: "formDescription" }] : []));
|
|
1649
|
-
actions = input(...(ngDevMode ? [undefined, { debugName: "actions" }] : []));
|
|
1650
|
-
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : []));
|
|
1651
|
-
showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : []));
|
|
1652
|
-
enableAutoSave = input(true, ...(ngDevMode ? [{ debugName: "enableAutoSave" }] : []));
|
|
1653
|
-
componentInstanceId = input(...(ngDevMode ? [undefined, { debugName: "componentInstanceId" }] : []));
|
|
2031
|
+
formId = input.required(...(ngDevMode ? [{ debugName: "formId" }] : /* istanbul ignore next */ []));
|
|
2032
|
+
formTitle = input(...(ngDevMode ? [undefined, { debugName: "formTitle" }] : /* istanbul ignore next */ []));
|
|
2033
|
+
formDescription = input(...(ngDevMode ? [undefined, { debugName: "formDescription" }] : /* istanbul ignore next */ []));
|
|
2034
|
+
actions = input(...(ngDevMode ? [undefined, { debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
2035
|
+
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
|
|
2036
|
+
showActions = input(true, ...(ngDevMode ? [{ debugName: "showActions" }] : /* istanbul ignore next */ []));
|
|
2037
|
+
enableAutoSave = input(true, ...(ngDevMode ? [{ debugName: "enableAutoSave" }] : /* istanbul ignore next */ []));
|
|
2038
|
+
componentInstanceId = input(...(ngDevMode ? [undefined, { debugName: "componentInstanceId" }] : /* istanbul ignore next */ []));
|
|
1654
2039
|
// Allows editor affordances (e.g., opening metadata editor on interactions)
|
|
1655
|
-
enableCustomization = input(false, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : []));
|
|
1656
|
-
persistenceOptions = input(...(ngDevMode ? [undefined, { debugName: "persistenceOptions" }] : []));
|
|
2040
|
+
enableCustomization = input(false, ...(ngDevMode ? [{ debugName: "enableCustomization" }] : /* istanbul ignore next */ []));
|
|
2041
|
+
persistenceOptions = input(...(ngDevMode ? [undefined, { debugName: "persistenceOptions" }] : /* istanbul ignore next */ []));
|
|
1657
2042
|
// When true, uses FormControlName.path (joined by '.') as FieldMetadata.name.
|
|
1658
2043
|
// Requires nested path support (already present in DynamicFormService).
|
|
1659
|
-
usePathNames = input(false, ...(ngDevMode ? [{ debugName: "usePathNames" }] : []));
|
|
2044
|
+
usePathNames = input(false, ...(ngDevMode ? [{ debugName: "usePathNames" }] : /* istanbul ignore next */ []));
|
|
1660
2045
|
// Debounce interval for autosave (ms). Only used when enableAutoSave is true.
|
|
1661
|
-
autoSaveDebounceMs = input(800, ...(ngDevMode ? [{ debugName: "autoSaveDebounceMs" }] : []));
|
|
2046
|
+
autoSaveDebounceMs = input(800, ...(ngDevMode ? [{ debugName: "autoSaveDebounceMs" }] : /* istanbul ignore next */ []));
|
|
1662
2047
|
submitted = output();
|
|
1663
2048
|
saved = output();
|
|
1664
2049
|
resetEvent = output({ alias: 'reset' });
|
|
@@ -1669,6 +2054,21 @@ class ManualFormComponent {
|
|
|
1669
2054
|
instance;
|
|
1670
2055
|
resolvedActions;
|
|
1671
2056
|
aiAdapter = new ManualFormAiAdapter(this);
|
|
2057
|
+
aiAssistantOpen = false;
|
|
2058
|
+
aiAssistantPrompt = '';
|
|
2059
|
+
aiAssistantViewState = null;
|
|
2060
|
+
aiAssistantLayout = createPraxisAssistantViewportLayout();
|
|
2061
|
+
aiAssistantLabels = {
|
|
2062
|
+
title: 'Copiloto semantico Praxis',
|
|
2063
|
+
subtitle: 'Converse, revise e governe ajustes do formulario manual.',
|
|
2064
|
+
prompt: 'Mensagem',
|
|
2065
|
+
promptPlaceholder: 'Descreva o ajuste que voce precisa no formulario.',
|
|
2066
|
+
emptyConversation: 'Diga o que voce quer alterar no formulario.',
|
|
2067
|
+
submit: 'Interpretar pedido',
|
|
2068
|
+
apply: 'Aplicar ajuste',
|
|
2069
|
+
};
|
|
2070
|
+
aiAssistantController = null;
|
|
2071
|
+
aiAssistantStateSubscription = null;
|
|
1672
2072
|
formGroup = new FormGroup({});
|
|
1673
2073
|
registeredDirectives = [];
|
|
1674
2074
|
constructor() {
|
|
@@ -1720,6 +2120,8 @@ class ManualFormComponent {
|
|
|
1720
2120
|
this.metadataSubscription?.unsubscribe();
|
|
1721
2121
|
this.toolbarOverlayRef?.dispose();
|
|
1722
2122
|
this.outsideClickSubscription?.unsubscribe();
|
|
2123
|
+
this.assistantSessions.removeContextSession(this.buildAiAssistantContextSnapshot().identity);
|
|
2124
|
+
this.aiAssistantStateSubscription?.unsubscribe();
|
|
1723
2125
|
}
|
|
1724
2126
|
// =============================
|
|
1725
2127
|
// ControlContainer interface
|
|
@@ -1945,6 +2347,317 @@ class ManualFormComponent {
|
|
|
1945
2347
|
this.metadataChange.emit(this.instance.currentConfig);
|
|
1946
2348
|
this.cdr.markForCheck();
|
|
1947
2349
|
}
|
|
2350
|
+
openAiAssistant() {
|
|
2351
|
+
this.initializeAiAssistantController();
|
|
2352
|
+
this.aiAssistantOpen = true;
|
|
2353
|
+
this.aiAssistantController?.setContextItems(this.buildAiAssistantContextItems());
|
|
2354
|
+
this.syncAiAssistantSession('active');
|
|
2355
|
+
this.cdr.markForCheck();
|
|
2356
|
+
}
|
|
2357
|
+
openAiAssistantFromSession(session) {
|
|
2358
|
+
if (session.id !== this.resolveAiAssistantSessionId())
|
|
2359
|
+
return;
|
|
2360
|
+
this.initializeAiAssistantController();
|
|
2361
|
+
this.aiAssistantOpen = true;
|
|
2362
|
+
this.aiAssistantController?.setContextItems(this.buildAiAssistantContextItems());
|
|
2363
|
+
this.syncAiAssistantSession('active');
|
|
2364
|
+
this.cdr.markForCheck();
|
|
2365
|
+
}
|
|
2366
|
+
closeAiAssistant() {
|
|
2367
|
+
this.aiAssistantOpen = false;
|
|
2368
|
+
this.syncAiAssistantSession('minimized');
|
|
2369
|
+
this.cdr.markForCheck();
|
|
2370
|
+
}
|
|
2371
|
+
onAiAssistantPromptChange(prompt) {
|
|
2372
|
+
this.aiAssistantPrompt = prompt;
|
|
2373
|
+
this.syncAiAssistantSession();
|
|
2374
|
+
}
|
|
2375
|
+
onAiAssistantSubmit(prompt) {
|
|
2376
|
+
this.aiAssistantController?.submitPrompt(prompt).subscribe((state) => {
|
|
2377
|
+
this.aiAssistantPrompt = '';
|
|
2378
|
+
this.aiAssistantViewState = state;
|
|
2379
|
+
this.syncAiAssistantSession();
|
|
2380
|
+
this.cdr.markForCheck();
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
onAiAssistantApply() {
|
|
2384
|
+
this.aiAssistantController?.apply().subscribe((state) => {
|
|
2385
|
+
this.aiAssistantViewState = state;
|
|
2386
|
+
this.syncAiAssistantSession();
|
|
2387
|
+
this.cdr.markForCheck();
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
onAiAssistantRetry() {
|
|
2391
|
+
this.aiAssistantController?.retry().subscribe((state) => {
|
|
2392
|
+
this.aiAssistantViewState = state;
|
|
2393
|
+
this.syncAiAssistantSession();
|
|
2394
|
+
this.cdr.markForCheck();
|
|
2395
|
+
});
|
|
2396
|
+
}
|
|
2397
|
+
onAiAssistantCancel() {
|
|
2398
|
+
this.aiAssistantController?.cancel().subscribe((state) => {
|
|
2399
|
+
this.aiAssistantPrompt = '';
|
|
2400
|
+
this.aiAssistantViewState = state;
|
|
2401
|
+
this.syncAiAssistantSession();
|
|
2402
|
+
this.cdr.markForCheck();
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
onAiAssistantQuickReply(reply) {
|
|
2406
|
+
const controller = this.aiAssistantController;
|
|
2407
|
+
if (!controller)
|
|
2408
|
+
return;
|
|
2409
|
+
const state = controller.snapshot();
|
|
2410
|
+
const contextHints = reply.contextHints ? { ...reply.contextHints } : undefined;
|
|
2411
|
+
const next$ = state.state === 'clarification'
|
|
2412
|
+
? controller.answerClarification({
|
|
2413
|
+
id: reply.id,
|
|
2414
|
+
label: reply.label,
|
|
2415
|
+
value: reply.prompt,
|
|
2416
|
+
description: reply.description ?? undefined,
|
|
2417
|
+
contextHints,
|
|
2418
|
+
})
|
|
2419
|
+
: controller.submitPrompt(reply.prompt, {
|
|
2420
|
+
kind: reply.kind || 'quick-reply',
|
|
2421
|
+
id: reply.id,
|
|
2422
|
+
value: reply.prompt,
|
|
2423
|
+
displayPrompt: reply.label,
|
|
2424
|
+
contextHints,
|
|
2425
|
+
});
|
|
2426
|
+
next$.subscribe((nextState) => {
|
|
2427
|
+
this.aiAssistantPrompt = '';
|
|
2428
|
+
this.aiAssistantViewState = nextState;
|
|
2429
|
+
this.syncAiAssistantSession();
|
|
2430
|
+
this.cdr.markForCheck();
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
onAiAssistantEditMessage(message) {
|
|
2434
|
+
this.aiAssistantPrompt = message.text;
|
|
2435
|
+
this.cdr.markForCheck();
|
|
2436
|
+
}
|
|
2437
|
+
onAiAssistantResendMessage(message) {
|
|
2438
|
+
this.aiAssistantController?.resendMessage(message.id).subscribe((state) => {
|
|
2439
|
+
this.aiAssistantPrompt = '';
|
|
2440
|
+
this.aiAssistantViewState = state;
|
|
2441
|
+
this.syncAiAssistantSession();
|
|
2442
|
+
this.cdr.markForCheck();
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2445
|
+
onAiAssistantLayoutChange(layout) {
|
|
2446
|
+
this.aiAssistantLayout = layout;
|
|
2447
|
+
}
|
|
2448
|
+
initializeAiAssistantController() {
|
|
2449
|
+
if (this.aiAssistantController)
|
|
2450
|
+
return;
|
|
2451
|
+
const flow = new ManualFormAgenticAuthoringTurnFlow(this.aiAdapter, this.aiApi);
|
|
2452
|
+
const controller = this.aiTurnOrchestrator.createController(flow, {
|
|
2453
|
+
componentId: this.aiAdapter.componentId || 'praxis-manual-form',
|
|
2454
|
+
componentType: this.aiAdapter.componentType || 'form',
|
|
2455
|
+
contextItems: this.buildAiAssistantContextItems(),
|
|
2456
|
+
});
|
|
2457
|
+
this.aiAssistantController = controller;
|
|
2458
|
+
this.aiAssistantViewState = controller.snapshot();
|
|
2459
|
+
this.aiAssistantStateSubscription?.unsubscribe();
|
|
2460
|
+
this.aiAssistantStateSubscription = controller.state$.subscribe((state) => {
|
|
2461
|
+
this.aiAssistantViewState = state;
|
|
2462
|
+
this.syncAiAssistantSession();
|
|
2463
|
+
this.cdr.markForCheck();
|
|
2464
|
+
});
|
|
2465
|
+
this.cdr.markForCheck();
|
|
2466
|
+
}
|
|
2467
|
+
buildAiAssistantContextItems() {
|
|
2468
|
+
const items = [
|
|
2469
|
+
{
|
|
2470
|
+
id: 'component',
|
|
2471
|
+
label: 'Componente',
|
|
2472
|
+
value: 'Formulario manual',
|
|
2473
|
+
kind: 'component',
|
|
2474
|
+
icon: 'edit_note',
|
|
2475
|
+
},
|
|
2476
|
+
{
|
|
2477
|
+
id: 'form-id',
|
|
2478
|
+
label: 'Formulario',
|
|
2479
|
+
value: this.safeAiAssistantFormId(),
|
|
2480
|
+
kind: 'custom',
|
|
2481
|
+
icon: 'tag',
|
|
2482
|
+
},
|
|
2483
|
+
];
|
|
2484
|
+
const fieldsCount = this.instance?.currentConfig?.fieldMetadata?.length ?? 0;
|
|
2485
|
+
if (fieldsCount > 0) {
|
|
2486
|
+
items.push({
|
|
2487
|
+
id: 'fields',
|
|
2488
|
+
label: 'Campos',
|
|
2489
|
+
value: String(fieldsCount),
|
|
2490
|
+
kind: 'custom',
|
|
2491
|
+
icon: 'view_list',
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
return items;
|
|
2495
|
+
}
|
|
2496
|
+
buildAiAssistantContextSnapshot() {
|
|
2497
|
+
const fieldNames = this.collectAiAssistantFieldNames();
|
|
2498
|
+
const counts = this.collectAiAssistantCounts();
|
|
2499
|
+
return {
|
|
2500
|
+
identity: {
|
|
2501
|
+
sessionId: this.resolveAiAssistantSessionId(),
|
|
2502
|
+
ownerId: this.resolveAiAssistantOwnerId(),
|
|
2503
|
+
ownerType: 'manual-form',
|
|
2504
|
+
componentId: 'praxis-manual-form',
|
|
2505
|
+
componentType: 'form',
|
|
2506
|
+
routeKey: this.resolveAiAssistantRouteKey(),
|
|
2507
|
+
},
|
|
2508
|
+
target: {
|
|
2509
|
+
kind: 'component',
|
|
2510
|
+
id: this.resolveAiAssistantOwnerId(),
|
|
2511
|
+
label: this.formTitle() || this.safeAiAssistantFormId(),
|
|
2512
|
+
metadata: {
|
|
2513
|
+
formId: this.safeAiAssistantFormId(),
|
|
2514
|
+
hasCustomization: !!this.enableCustomization(),
|
|
2515
|
+
},
|
|
2516
|
+
},
|
|
2517
|
+
contextItems: this.buildAiAssistantContextItems().map((item) => ({
|
|
2518
|
+
id: item.id,
|
|
2519
|
+
label: item.label,
|
|
2520
|
+
value: item.value || '',
|
|
2521
|
+
kind: item.kind,
|
|
2522
|
+
})),
|
|
2523
|
+
mode: 'agentic-authoring',
|
|
2524
|
+
authoringManifestRef: {
|
|
2525
|
+
componentId: 'praxis-manual-form',
|
|
2526
|
+
source: 'PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST',
|
|
2527
|
+
},
|
|
2528
|
+
schemaFields: fieldNames.length ? fieldNames : undefined,
|
|
2529
|
+
dataProfileDigest: {
|
|
2530
|
+
summary: `${counts.fieldCount} campo(s), ${counts.sectionCount} secao(oes), ${counts.actionCount} acao(oes)`,
|
|
2531
|
+
counts,
|
|
2532
|
+
},
|
|
2533
|
+
runtimeStateDigest: {
|
|
2534
|
+
summary: this.instance
|
|
2535
|
+
? `Formulario ${this.formGroup.valid ? 'valido' : 'invalido'} e ${this.formGroup.dirty ? 'alterado' : 'sem alteracoes'}`
|
|
2536
|
+
: 'Formulario ainda sem instancia runtime.',
|
|
2537
|
+
fields: [
|
|
2538
|
+
'currentConfig',
|
|
2539
|
+
'fieldMetadata',
|
|
2540
|
+
'form',
|
|
2541
|
+
'metadataChange',
|
|
2542
|
+
],
|
|
2543
|
+
},
|
|
2544
|
+
capabilityRefs: [
|
|
2545
|
+
{
|
|
2546
|
+
id: 'manual-form.component-edit-plan',
|
|
2547
|
+
label: 'Plano de edicao de formulario manual',
|
|
2548
|
+
source: 'PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST',
|
|
2549
|
+
risk: 'medium',
|
|
2550
|
+
},
|
|
2551
|
+
],
|
|
2552
|
+
governanceHints: [
|
|
2553
|
+
{
|
|
2554
|
+
kind: 'business-rule-boundary',
|
|
2555
|
+
label: 'Regras compartilhadas exigem governanca',
|
|
2556
|
+
reason: 'Politicas, validacoes reutilizaveis e compliance nao devem ser aplicados como patch local do formulario.',
|
|
2557
|
+
risk: 'high',
|
|
2558
|
+
},
|
|
2559
|
+
],
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
syncAiAssistantSession(visibility = null) {
|
|
2563
|
+
if (!this.enableCustomization())
|
|
2564
|
+
return;
|
|
2565
|
+
if (!this.aiAssistantOpen && !this.hasAiAssistantSessionState() && visibility !== 'minimized')
|
|
2566
|
+
return;
|
|
2567
|
+
const state = this.aiAssistantViewState;
|
|
2568
|
+
this.assistantSessions.upsertContextSession(this.buildAiAssistantContextSnapshot(), {
|
|
2569
|
+
title: 'Copiloto semantico Praxis',
|
|
2570
|
+
summary: this.resolveAiAssistantSummary(),
|
|
2571
|
+
mode: state?.mode || 'agentic-authoring',
|
|
2572
|
+
state: state?.state || 'idle',
|
|
2573
|
+
visibility: visibility ?? (this.aiAssistantOpen ? 'active' : 'minimized'),
|
|
2574
|
+
badge: this.resolveAiAssistantBadge(),
|
|
2575
|
+
icon: this.resolveAiAssistantIcon(),
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
hasAiAssistantSessionState() {
|
|
2579
|
+
return !!this.aiAssistantPrompt.trim()
|
|
2580
|
+
|| !!this.aiAssistantViewState?.messages?.length
|
|
2581
|
+
|| !!this.aiAssistantViewState?.quickReplies?.length
|
|
2582
|
+
|| !!this.aiAssistantViewState?.pendingPatch
|
|
2583
|
+
|| !!this.aiAssistantViewState?.statusText?.trim()
|
|
2584
|
+
|| !!this.aiAssistantViewState?.errorText?.trim();
|
|
2585
|
+
}
|
|
2586
|
+
resolveAiAssistantSessionId() {
|
|
2587
|
+
return `manual-form:${this.resolveAiAssistantRouteKey()}:${this.resolveAiAssistantOwnerId()}`;
|
|
2588
|
+
}
|
|
2589
|
+
resolveAiAssistantOwnerId() {
|
|
2590
|
+
return (this.componentInstanceId() || this.safeAiAssistantFormId() || 'manual-form').trim() || 'manual-form';
|
|
2591
|
+
}
|
|
2592
|
+
safeAiAssistantFormId() {
|
|
2593
|
+
try {
|
|
2594
|
+
return String(this.formId() || '').trim();
|
|
2595
|
+
}
|
|
2596
|
+
catch {
|
|
2597
|
+
return '';
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
resolveAiAssistantRouteKey() {
|
|
2601
|
+
const routePath = this.route?.snapshot?.routeConfig?.path?.trim();
|
|
2602
|
+
return routePath || 'local';
|
|
2603
|
+
}
|
|
2604
|
+
resolveAiAssistantSummary() {
|
|
2605
|
+
const status = this.aiAssistantViewState?.statusText?.trim();
|
|
2606
|
+
if (status)
|
|
2607
|
+
return status;
|
|
2608
|
+
const error = this.aiAssistantViewState?.errorText?.trim();
|
|
2609
|
+
if (error)
|
|
2610
|
+
return error;
|
|
2611
|
+
const prompt = this.aiAssistantPrompt.trim();
|
|
2612
|
+
if (prompt)
|
|
2613
|
+
return prompt.length > 96 ? `${prompt.slice(0, 93)}...` : prompt;
|
|
2614
|
+
const lastMessage = [...(this.aiAssistantViewState?.messages ?? [])].reverse()
|
|
2615
|
+
.find((message) => message.role === 'assistant' || message.role === 'user');
|
|
2616
|
+
if (lastMessage?.text) {
|
|
2617
|
+
return lastMessage.text.length > 96 ? `${lastMessage.text.slice(0, 93)}...` : lastMessage.text;
|
|
2618
|
+
}
|
|
2619
|
+
return 'Assistente contextual do formulario manual.';
|
|
2620
|
+
}
|
|
2621
|
+
resolveAiAssistantBadge() {
|
|
2622
|
+
const state = this.aiAssistantViewState?.state;
|
|
2623
|
+
if (state === 'error')
|
|
2624
|
+
return 'erro';
|
|
2625
|
+
if (state === 'clarification')
|
|
2626
|
+
return 'revisar';
|
|
2627
|
+
if (state === 'review')
|
|
2628
|
+
return 'preview';
|
|
2629
|
+
if (state === 'success')
|
|
2630
|
+
return 'ok';
|
|
2631
|
+
return undefined;
|
|
2632
|
+
}
|
|
2633
|
+
resolveAiAssistantIcon() {
|
|
2634
|
+
const state = this.aiAssistantViewState?.state;
|
|
2635
|
+
if (state === 'error')
|
|
2636
|
+
return 'error';
|
|
2637
|
+
if (state === 'clarification')
|
|
2638
|
+
return 'rule';
|
|
2639
|
+
if (state === 'review')
|
|
2640
|
+
return 'rate_review';
|
|
2641
|
+
return 'auto_awesome';
|
|
2642
|
+
}
|
|
2643
|
+
collectAiAssistantFieldNames() {
|
|
2644
|
+
return Array.from(new Set((this.instance?.currentConfig?.fieldMetadata ?? [])
|
|
2645
|
+
.map((field) => field.name)
|
|
2646
|
+
.filter((name) => typeof name === 'string' && !!name.trim())));
|
|
2647
|
+
}
|
|
2648
|
+
collectAiAssistantCounts() {
|
|
2649
|
+
const config = this.instance?.currentConfig;
|
|
2650
|
+
return {
|
|
2651
|
+
sectionCount: config?.sections?.length ?? 0,
|
|
2652
|
+
fieldCount: config?.fieldMetadata?.length ?? 0,
|
|
2653
|
+
actionCount: [
|
|
2654
|
+
config?.actions?.submit,
|
|
2655
|
+
config?.actions?.cancel,
|
|
2656
|
+
config?.actions?.reset,
|
|
2657
|
+
...(config?.actions?.custom ?? []),
|
|
2658
|
+
].filter(Boolean).length,
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
1948
2661
|
async initialize(fromChanges) {
|
|
1949
2662
|
this.syncHostFormGroupReference();
|
|
1950
2663
|
if (!this.formId()) {
|
|
@@ -2536,24 +3249,23 @@ class ManualFormComponent {
|
|
|
2536
3249
|
resetButtonLabel: source.resetButtonLabel ?? base.resetButtonLabel,
|
|
2537
3250
|
};
|
|
2538
3251
|
}
|
|
2539
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2540
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
3252
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3253
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormComponent, isStandalone: true, selector: "praxis-manual-form", inputs: { formId: { classPropertyName: "formId", publicName: "formId", isSignal: true, isRequired: true, transformFunction: null }, formTitle: { classPropertyName: "formTitle", publicName: "formTitle", isSignal: true, isRequired: false, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null }, enableAutoSave: { classPropertyName: "enableAutoSave", publicName: "enableAutoSave", isSignal: true, isRequired: false, transformFunction: null }, componentInstanceId: { classPropertyName: "componentInstanceId", publicName: "componentInstanceId", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, persistenceOptions: { classPropertyName: "persistenceOptions", publicName: "persistenceOptions", isSignal: true, isRequired: false, transformFunction: null }, usePathNames: { classPropertyName: "usePathNames", publicName: "usePathNames", isSignal: true, isRequired: false, transformFunction: null }, autoSaveDebounceMs: { classPropertyName: "autoSaveDebounceMs", publicName: "autoSaveDebounceMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submitted: "submitted", saved: "saved", resetEvent: "reset", metadataChange: "metadataChange" }, providers: [
|
|
2541
3254
|
// Provide a ControlContainer at the host boundary so projected formControlName can resolve it
|
|
2542
3255
|
{ provide: ControlContainer, useExisting: ManualFormComponent },
|
|
2543
|
-
], queries: [{ propertyName: "formControls", predicate: FormControlName, descendants: true }], ngImport: i0, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <praxis-ai-assistant [
|
|
3256
|
+
], queries: [{ propertyName: "formControls", predicate: FormControlName, descendants: true }], ngImport: i0, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario manual\"\n data-testid=\"praxis-manual-form-ai-assistant-trigger\"\n >\n Copiloto Praxis\n </button>\n </div>\n }\n\n @if (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=\"praxis-manual-form-ai-assistant\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (close)=\"closeAiAssistant()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n ></praxis-ai-assistant-shell>\n }\n\n <form class=\"pdx-manual-form__form\" [formGroup]=\"formGroup\" (submit)=\"handleSubmit(); $event.preventDefault()\">\n <ng-content></ng-content>\n </form>\n\n @if (showActions() && resolvedActions) {\n <praxis-manual-form-actions [actions]=\"resolvedActions\"\n (actionClick)=\"handleAction($event)\"></praxis-manual-form-actions>\n }\n</div>\n", styles: [".pdx-manual-form{display:flex;flex-direction:column;gap:var(--pdx-manual-form-gap, 24px);color:var(--md-sys-color-on-surface)}.pdx-manual-form__form{display:grid;gap:var(--pdx-manual-form-field-gap, 16px);padding:var(--pdx-manual-form-padding, 20px);border-radius:var(--pdx-manual-form-radius, 16px);background:var(--pdx-manual-form-surface, var(--md-sys-color-surface-container));border:1px solid var(--pdx-manual-form-outline, var(--md-sys-color-outline-variant));box-shadow:var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__form:focus-within{border-color:var(--pdx-manual-form-focus, var(--md-sys-color-primary));box-shadow:0 0 0 2px var(--md-sys-color-primary),var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__assistant{display:flex;justify-content:flex-end}.pdx-manual-form__assistant-trigger{border:0;border-radius:999px;padding:8px 14px;cursor:pointer;color:var(--md-sys-color-on-primary, #fff);background:var(--md-sys-color-primary, #3451d1);box-shadow:var(--md-sys-elevation-level2, 0 4px 12px rgba(0, 0, 0, .18))}.pdx-manual-form__assistant-trigger:hover{background:var(--md-sys-color-primary-container, #223fb6)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "layoutChange"] }, { kind: "component", type: ManualFormHeaderComponent, selector: "praxis-manual-form-header", inputs: ["instance", "title", "description", "saveLabel", "resetLabel", "enableCustomization", "editFormLabel"], outputs: ["save", "reset", "editForm"] }, { kind: "component", type: ManualFormActionsComponent, selector: "praxis-manual-form-actions", inputs: ["actions", "trackByFn"], outputs: ["actionClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2544
3257
|
}
|
|
2545
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3258
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormComponent, decorators: [{
|
|
2546
3259
|
type: Component,
|
|
2547
3260
|
args: [{ selector: 'praxis-manual-form', standalone: true, imports: [
|
|
2548
|
-
CommonModule,
|
|
2549
3261
|
ReactiveFormsModule,
|
|
2550
|
-
|
|
3262
|
+
PraxisAiAssistantShellComponent,
|
|
2551
3263
|
ManualFormHeaderComponent,
|
|
2552
|
-
ManualFormActionsComponent
|
|
3264
|
+
ManualFormActionsComponent
|
|
2553
3265
|
], providers: [
|
|
2554
3266
|
// Provide a ControlContainer at the host boundary so projected formControlName can resolve it
|
|
2555
3267
|
{ provide: ControlContainer, useExisting: ManualFormComponent },
|
|
2556
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <praxis-ai-assistant [
|
|
3268
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pdx-manual-form\">\n @if (showHeader()) {\n <praxis-manual-form-header [instance]=\"instance\" [title]=\"formTitle()\" [description]=\"formDescription()\"\n [enableCustomization]=\"enableCustomization()\" (editForm)=\"openFormEditor()\" (save)=\"handleSave()\"\n (reset)=\"handleReset()\"></praxis-manual-form-header>\n }\n\n @if (enableCustomization()) {\n <div class=\"pdx-manual-form__assistant\">\n <button\n type=\"button\"\n class=\"pdx-manual-form__assistant-trigger\"\n (click)=\"openAiAssistant()\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario manual\"\n data-testid=\"praxis-manual-form-ai-assistant-trigger\"\n >\n Copiloto Praxis\n </button>\n </div>\n }\n\n @if (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=\"praxis-manual-form-ai-assistant\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (close)=\"closeAiAssistant()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n ></praxis-ai-assistant-shell>\n }\n\n <form class=\"pdx-manual-form__form\" [formGroup]=\"formGroup\" (submit)=\"handleSubmit(); $event.preventDefault()\">\n <ng-content></ng-content>\n </form>\n\n @if (showActions() && resolvedActions) {\n <praxis-manual-form-actions [actions]=\"resolvedActions\"\n (actionClick)=\"handleAction($event)\"></praxis-manual-form-actions>\n }\n</div>\n", styles: [".pdx-manual-form{display:flex;flex-direction:column;gap:var(--pdx-manual-form-gap, 24px);color:var(--md-sys-color-on-surface)}.pdx-manual-form__form{display:grid;gap:var(--pdx-manual-form-field-gap, 16px);padding:var(--pdx-manual-form-padding, 20px);border-radius:var(--pdx-manual-form-radius, 16px);background:var(--pdx-manual-form-surface, var(--md-sys-color-surface-container));border:1px solid var(--pdx-manual-form-outline, var(--md-sys-color-outline-variant));box-shadow:var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__form:focus-within{border-color:var(--pdx-manual-form-focus, var(--md-sys-color-primary));box-shadow:0 0 0 2px var(--md-sys-color-primary),var(--pdx-manual-form-shadow, var(--md-sys-elevation-level1, none))}.pdx-manual-form__assistant{display:flex;justify-content:flex-end}.pdx-manual-form__assistant-trigger{border:0;border-radius:999px;padding:8px 14px;cursor:pointer;color:var(--md-sys-color-on-primary, #fff);background:var(--md-sys-color-primary, #3451d1);box-shadow:var(--md-sys-elevation-level2, 0 4px 12px rgba(0, 0, 0, .18))}.pdx-manual-form__assistant-trigger:hover{background:var(--md-sys-color-primary-container, #223fb6)}\n"] }]
|
|
2557
3269
|
}], ctorParameters: () => [], propDecorators: { formId: [{ type: i0.Input, args: [{ isSignal: true, alias: "formId", required: true }] }], formTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "formTitle", required: false }] }], formDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "formDescription", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], enableAutoSave: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableAutoSave", required: false }] }], componentInstanceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "componentInstanceId", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], persistenceOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "persistenceOptions", required: false }] }], usePathNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "usePathNames", required: false }] }], autoSaveDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSaveDebounceMs", required: false }] }], submitted: [{ type: i0.Output, args: ["submitted"] }], saved: [{ type: i0.Output, args: ["saved"] }], resetEvent: [{ type: i0.Output, args: ["reset"] }], metadataChange: [{ type: i0.Output, args: ["metadataChange"] }], formControls: [{
|
|
2558
3270
|
type: ContentChildren,
|
|
2559
3271
|
args: [FormControlName, { descendants: true }]
|
|
@@ -3308,8 +4020,8 @@ class ManualFormConfigEditorComponent {
|
|
|
3308
4020
|
}
|
|
3309
4021
|
return next;
|
|
3310
4022
|
}
|
|
3311
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3312
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
4023
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormConfigEditorComponent, deps: [{ token: SETTINGS_PANEL_DATA }, { token: SETTINGS_PANEL_REF }], target: i0.ɵɵFactoryTarget.Component });
|
|
4024
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormConfigEditorComponent, isStandalone: true, selector: "praxis-manual-form-config-editor", providers: [providePraxisManualFormI18n()], ngImport: i0, template: `
|
|
3313
4025
|
<div class="mf-editor">
|
|
3314
4026
|
<div class="mf-editor__toolbar">
|
|
3315
4027
|
<div class="mf-editor__title">
|
|
@@ -4088,12 +4800,11 @@ class ManualFormConfigEditorComponent {
|
|
|
4088
4800
|
</mat-tab>
|
|
4089
4801
|
</mat-tab-group>
|
|
4090
4802
|
</div>
|
|
4091
|
-
`, isInline: true, styles: [".mf-editor{display:grid;gap:16px;padding:16px;color:var(--md-sys-color-on-surface)}.mf-editor__toolbar{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container)}.mf-editor__title{display:flex;flex-direction:column;gap:2px;font-weight:600}.mf-editor__subtitle{font-weight:400;color:var(--md-sys-color-on-surface-variant)}.mf-editor__toolbar .spacer{flex:1}.mf-tabs{min-height:420px}.mf-tab{display:grid;gap:16px;padding:14px 6px 0}.mf-editor__list{display:grid;gap:8px;overflow-x:auto}.mf-editor__row{display:grid;grid-template-columns:2.2fr 2fr 1fr repeat(4,minmax(90px,.8fr));align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);min-width:720px}.mf-editor__row--head{font-weight:600;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface-container)}.mf-editor__filter{display:inline-flex;align-items:center;gap:8px;font-weight:500}.mf-editor__filter input{accent-color:var(--md-sys-color-primary)}.col code{display:inline-block;font-family:inherit;font-size:.85rem;padding:2px 8px;border-radius:6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant)}.mf-btn{min-height:36px;padding:0 12px;border-radius:8px;border:1px solid var(--md-sys-color-outline);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.mf-btn:hover{background:var(--md-sys-color-surface-container)}.mf-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.toggle{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant)}.mf-section{display:grid;gap:12px;padding:16px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.mf-section--full{padding:10px}.mf-section__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.mf-section__header h3{margin:0;font-size:1.05rem;font-weight:600}.mf-help{margin:6px 0 0;font-size:.9rem;color:var(--md-sys-color-on-surface-variant)}.mf-note{padding:10px 12px;border-radius:10px;border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:.9rem}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}.mf-actions-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}.mf-action-card,.mf-custom-card,.mf-custom-message-card{display:grid;gap:10px;padding:14px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high)}.mf-action-card__title,.mf-custom-card__title{font-weight:600;color:var(--md-sys-color-on-surface)}.mf-actions-layout{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;align-items:center}.mf-toggle-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;align-items:start}.mf-hooks-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}.mf-hook-field textarea{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.85rem}.mf-actions-row{display:inline-flex;gap:8px;align-items:center}.mf-actions-row--end{justify-content:flex-end;width:100%}.mf-custom-actions,.mf-custom-messages{display:grid;gap:12px}.mf-custom-card__header{display:flex;align-items:center;justify-content:space-between;gap:8px}.mf-custom-card__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;align-items:center}.mf-messages-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}.mf-empty{margin:0;color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type:
|
|
4803
|
+
`, isInline: true, styles: [".mf-editor{display:grid;gap:16px;padding:16px;color:var(--md-sys-color-on-surface)}.mf-editor__toolbar{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container)}.mf-editor__title{display:flex;flex-direction:column;gap:2px;font-weight:600}.mf-editor__subtitle{font-weight:400;color:var(--md-sys-color-on-surface-variant)}.mf-editor__toolbar .spacer{flex:1}.mf-tabs{min-height:420px}.mf-tab{display:grid;gap:16px;padding:14px 6px 0}.mf-editor__list{display:grid;gap:8px;overflow-x:auto}.mf-editor__row{display:grid;grid-template-columns:2.2fr 2fr 1fr repeat(4,minmax(90px,.8fr));align-items:center;gap:8px;padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);min-width:720px}.mf-editor__row--head{font-weight:600;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface-container)}.mf-editor__filter{display:inline-flex;align-items:center;gap:8px;font-weight:500}.mf-editor__filter input{accent-color:var(--md-sys-color-primary)}.col code{display:inline-block;font-family:inherit;font-size:.85rem;padding:2px 8px;border-radius:6px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant)}.mf-btn{min-height:36px;padding:0 12px;border-radius:8px;border:1px solid var(--md-sys-color-outline);background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface);cursor:pointer;transition:background-color .18s ease,border-color .18s ease,color .18s ease}.mf-btn:hover{background:var(--md-sys-color-surface-container)}.mf-btn:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.toggle{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant)}.mf-section{display:grid;gap:12px;padding:16px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.mf-section--full{padding:10px}.mf-section__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.mf-section__header h3{margin:0;font-size:1.05rem;font-weight:600}.mf-help{margin:6px 0 0;font-size:.9rem;color:var(--md-sys-color-on-surface-variant)}.mf-note{padding:10px 12px;border-radius:10px;border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:.9rem}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}.mf-actions-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}.mf-action-card,.mf-custom-card,.mf-custom-message-card{display:grid;gap:10px;padding:14px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-high)}.mf-action-card__title,.mf-custom-card__title{font-weight:600;color:var(--md-sys-color-on-surface)}.mf-actions-layout{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;align-items:center}.mf-toggle-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;align-items:start}.mf-hooks-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px}.mf-hook-field textarea{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.85rem}.mf-actions-row{display:inline-flex;gap:8px;align-items:center}.mf-actions-row--end{justify-content:flex-end;width:100%}.mf-custom-actions,.mf-custom-messages{display:grid;gap:12px}.mf-custom-card__header{display:flex;align-items:center;justify-content:space-between;gap:8px}.mf-custom-card__grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;align-items:center}.mf-messages-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px}.mf-empty{margin:0;color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: CascadeManagerTabComponent, selector: "praxis-cascade-manager-tab", inputs: ["fields", "connections"], outputs: ["apply", "cancel"] }] });
|
|
4092
4804
|
}
|
|
4093
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4805
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormConfigEditorComponent, decorators: [{
|
|
4094
4806
|
type: Component,
|
|
4095
4807
|
args: [{ selector: 'praxis-manual-form-config-editor', standalone: true, imports: [
|
|
4096
|
-
CommonModule,
|
|
4097
4808
|
FormsModule,
|
|
4098
4809
|
MatTabsModule,
|
|
4099
4810
|
MatFormFieldModule,
|
|
@@ -4103,7 +4814,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
4103
4814
|
MatButtonModule,
|
|
4104
4815
|
MatIconModule,
|
|
4105
4816
|
MatTooltipModule,
|
|
4106
|
-
CascadeManagerTabComponent
|
|
4817
|
+
CascadeManagerTabComponent
|
|
4107
4818
|
], providers: [providePraxisManualFormI18n()], template: `
|
|
4108
4819
|
<div class="mf-editor">
|
|
4109
4820
|
<div class="mf-editor__toolbar">
|
|
@@ -4991,21 +5702,21 @@ var manualFormConfigEditor_component = /*#__PURE__*/Object.freeze({
|
|
|
4991
5702
|
|
|
4992
5703
|
let nextDocExampleId = 0;
|
|
4993
5704
|
class ManualFormDocExampleComponent {
|
|
4994
|
-
title = input('Exemplo didatico', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
4995
|
-
subtitle = input(null, ...(ngDevMode ? [{ debugName: "subtitle" }] : []));
|
|
4996
|
-
level = input('Basico', ...(ngDevMode ? [{ debugName: "level" }] : []));
|
|
4997
|
-
bannerTitle = input(null, ...(ngDevMode ? [{ debugName: "bannerTitle" }] : []));
|
|
4998
|
-
bannerDescription = input(null, ...(ngDevMode ? [{ debugName: "bannerDescription" }] : []));
|
|
4999
|
-
templateCode = input('', ...(ngDevMode ? [{ debugName: "templateCode" }] : []));
|
|
5000
|
-
tsCode = input('', ...(ngDevMode ? [{ debugName: "tsCode" }] : []));
|
|
5001
|
-
configCode = input('', ...(ngDevMode ? [{ debugName: "configCode" }] : []));
|
|
5002
|
-
customizationEnabled = input(false, ...(ngDevMode ? [{ debugName: "customizationEnabled" }] : []));
|
|
5003
|
-
showCustomizationToggle = input(true, ...(ngDevMode ? [{ debugName: "showCustomizationToggle" }] : []));
|
|
5004
|
-
important = input(null, ...(ngDevMode ? [{ debugName: "important" }] : []));
|
|
5005
|
-
note = input(null, ...(ngDevMode ? [{ debugName: "note" }] : []));
|
|
5006
|
-
tip = input(null, ...(ngDevMode ? [{ debugName: "tip" }] : []));
|
|
5007
|
-
activeTab = signal('live', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
|
|
5008
|
-
copyStatus = signal('', ...(ngDevMode ? [{ debugName: "copyStatus" }] : []));
|
|
5705
|
+
title = input('Exemplo didatico', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
5706
|
+
subtitle = input(null, ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
5707
|
+
level = input('Basico', ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
|
|
5708
|
+
bannerTitle = input(null, ...(ngDevMode ? [{ debugName: "bannerTitle" }] : /* istanbul ignore next */ []));
|
|
5709
|
+
bannerDescription = input(null, ...(ngDevMode ? [{ debugName: "bannerDescription" }] : /* istanbul ignore next */ []));
|
|
5710
|
+
templateCode = input('', ...(ngDevMode ? [{ debugName: "templateCode" }] : /* istanbul ignore next */ []));
|
|
5711
|
+
tsCode = input('', ...(ngDevMode ? [{ debugName: "tsCode" }] : /* istanbul ignore next */ []));
|
|
5712
|
+
configCode = input('', ...(ngDevMode ? [{ debugName: "configCode" }] : /* istanbul ignore next */ []));
|
|
5713
|
+
customizationEnabled = input(false, ...(ngDevMode ? [{ debugName: "customizationEnabled" }] : /* istanbul ignore next */ []));
|
|
5714
|
+
showCustomizationToggle = input(true, ...(ngDevMode ? [{ debugName: "showCustomizationToggle" }] : /* istanbul ignore next */ []));
|
|
5715
|
+
important = input(null, ...(ngDevMode ? [{ debugName: "important" }] : /* istanbul ignore next */ []));
|
|
5716
|
+
note = input(null, ...(ngDevMode ? [{ debugName: "note" }] : /* istanbul ignore next */ []));
|
|
5717
|
+
tip = input(null, ...(ngDevMode ? [{ debugName: "tip" }] : /* istanbul ignore next */ []));
|
|
5718
|
+
activeTab = signal('live', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
5719
|
+
copyStatus = signal('', ...(ngDevMode ? [{ debugName: "copyStatus" }] : /* istanbul ignore next */ []));
|
|
5009
5720
|
tabs = [
|
|
5010
5721
|
{ id: 'live', label: 'Live', hint: 'Renderizacao do exemplo' },
|
|
5011
5722
|
{ id: 'template', label: 'Template', hint: 'Markup HTML do exemplo' },
|
|
@@ -5023,7 +5734,7 @@ class ManualFormDocExampleComponent {
|
|
|
5023
5734
|
default:
|
|
5024
5735
|
return '';
|
|
5025
5736
|
}
|
|
5026
|
-
}, ...(ngDevMode ? [{ debugName: "selectedSnippet" }] : []));
|
|
5737
|
+
}, ...(ngDevMode ? [{ debugName: "selectedSnippet" }] : /* istanbul ignore next */ []));
|
|
5027
5738
|
selectedSnippetLabel = computed(() => {
|
|
5028
5739
|
switch (this.activeTab()) {
|
|
5029
5740
|
case 'template':
|
|
@@ -5035,8 +5746,8 @@ class ManualFormDocExampleComponent {
|
|
|
5035
5746
|
default:
|
|
5036
5747
|
return 'Live';
|
|
5037
5748
|
}
|
|
5038
|
-
}, ...(ngDevMode ? [{ debugName: "selectedSnippetLabel" }] : []));
|
|
5039
|
-
canCopySnippet = computed(() => this.selectedSnippet().trim().length > 0, ...(ngDevMode ? [{ debugName: "canCopySnippet" }] : []));
|
|
5749
|
+
}, ...(ngDevMode ? [{ debugName: "selectedSnippetLabel" }] : /* istanbul ignore next */ []));
|
|
5750
|
+
canCopySnippet = computed(() => this.selectedSnippet().trim().length > 0, ...(ngDevMode ? [{ debugName: "canCopySnippet" }] : /* istanbul ignore next */ []));
|
|
5040
5751
|
tabChange = output();
|
|
5041
5752
|
customizationEnabledChange = output();
|
|
5042
5753
|
codeCopied = output();
|
|
@@ -5099,12 +5810,12 @@ class ManualFormDocExampleComponent {
|
|
|
5099
5810
|
this.copyStatusTimer = null;
|
|
5100
5811
|
}
|
|
5101
5812
|
}
|
|
5102
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5103
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
5813
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormDocExampleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5814
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ManualFormDocExampleComponent, isStandalone: true, selector: "praxis-manual-form-doc-example", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, bannerTitle: { classPropertyName: "bannerTitle", publicName: "bannerTitle", isSignal: true, isRequired: false, transformFunction: null }, bannerDescription: { classPropertyName: "bannerDescription", publicName: "bannerDescription", isSignal: true, isRequired: false, transformFunction: null }, templateCode: { classPropertyName: "templateCode", publicName: "templateCode", isSignal: true, isRequired: false, transformFunction: null }, tsCode: { classPropertyName: "tsCode", publicName: "tsCode", isSignal: true, isRequired: false, transformFunction: null }, configCode: { classPropertyName: "configCode", publicName: "configCode", isSignal: true, isRequired: false, transformFunction: null }, customizationEnabled: { classPropertyName: "customizationEnabled", publicName: "customizationEnabled", isSignal: true, isRequired: false, transformFunction: null }, showCustomizationToggle: { classPropertyName: "showCustomizationToggle", publicName: "showCustomizationToggle", isSignal: true, isRequired: false, transformFunction: null }, important: { classPropertyName: "important", publicName: "important", isSignal: true, isRequired: false, transformFunction: null }, note: { classPropertyName: "note", publicName: "note", isSignal: true, isRequired: false, transformFunction: null }, tip: { classPropertyName: "tip", publicName: "tip", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tabChange: "tabChange", customizationEnabledChange: "customizationEnabledChange", codeCopied: "codeCopied" }, ngImport: i0, template: "<section class=\"doc-example\" [attr.data-level]=\"level()\">\n @if (bannerTitle() || bannerDescription()) {\n <header class=\"doc-example__banner\">\n <div class=\"doc-example__banner-copy\">\n @if (bannerTitle()) {\n <h2>{{ bannerTitle() }}</h2>\n }\n @if (bannerDescription()) {\n <p>{{ bannerDescription() }}</p>\n }\n </div>\n <div class=\"doc-example__banner-art\">\n <ng-content select=\"[exampleBannerArtwork]\"></ng-content>\n </div>\n </header>\n }\n\n <div class=\"doc-example__summary\">\n <div class=\"doc-example__summary-main\">\n <span class=\"badge badge--level\">{{ level() }}</span>\n <h3>{{ title() }}</h3>\n @if (subtitle()) {\n <p>{{ subtitle() }}</p>\n }\n </div>\n\n @if (showCustomizationToggle()) {\n <button\n type=\"button\"\n class=\"mode-toggle\"\n [attr.aria-pressed]=\"customizationEnabled()\"\n [attr.aria-label]=\"customizationEnabled() ? 'Desligar modo de customizacao' : 'Ligar modo de customizacao'\"\n (click)=\"toggleCustomization()\"\n >\n {{ customizationEnabled() ? 'Customizacao: ligada' : 'Customizacao: desligada' }}\n </button>\n }\n </div>\n\n <p class=\"sr-only\" [attr.id]=\"idPrefix + '-tabs-help'\">\n Escolha entre visualizacao live, template, TypeScript ou config do exemplo.\n </p>\n\n <div class=\"doc-example__tabs\" role=\"tablist\" [attr.aria-describedby]=\"idPrefix + '-tabs-help'\">\n @for (tab of tabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"doc-example__tab\"\n [class.is-active]=\"activeTab() === tab.id\"\n [attr.id]=\"tabId(tab.id)\"\n [attr.aria-controls]=\"panelId(tab.id)\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n [attr.aria-label]=\"tab.label + ': ' + tab.hint\"\n (click)=\"setTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <section\n class=\"doc-example__panel\"\n role=\"tabpanel\"\n [attr.id]=\"panelId(activeTab())\"\n [attr.aria-labelledby]=\"tabId(activeTab())\"\n >\n @if (activeTab() === 'live') {\n <div class=\"doc-example__live\">\n <ng-content select=\"[exampleLive]\"></ng-content>\n </div>\n } @else {\n <div class=\"doc-example__code-toolbar\">\n <span class=\"doc-example__code-label\">{{ selectedSnippetLabel() }}</span>\n <button type=\"button\" class=\"copy-btn\" [disabled]=\"!canCopySnippet()\" (click)=\"copyActiveSnippet()\">\n Copiar\n </button>\n @if (copyStatus()) {\n <span class=\"copy-status\" aria-live=\"polite\">{{ copyStatus() }}</span>\n }\n </div>\n <pre class=\"doc-example__code\"><code>{{ selectedSnippet() }}</code></pre>\n }\n </section>\n\n <ng-content select=\"[exampleDiagram]\"></ng-content>\n\n @if (important() || note() || tip()) {\n <div class=\"doc-example__callouts\">\n @if (important()) {\n <p class=\"callout callout--important\"><strong>IMPORTANTE:</strong> {{ important() }}</p>\n }\n @if (note()) {\n <p class=\"callout callout--note\"><strong>NOTA:</strong> {{ note() }}</p>\n }\n @if (tip()) {\n <p class=\"callout callout--tip\"><strong>DICA:</strong> {{ tip() }}</p>\n }\n </div>\n }\n</section>\n", styles: [":host{display:block}.doc-example{--doc-accent: #007a6f;--doc-surface: var(--md-sys-color-surface, #fff);--doc-outline: color-mix(in srgb, var(--doc-accent) 30%, #d6dde1);display:grid;gap:16px;padding:18px;border-radius:18px;border:1px solid var(--doc-outline);background:radial-gradient(140% 120% at 0% 0%,color-mix(in srgb,var(--doc-accent) 10%,transparent),transparent 55%),var(--doc-surface);box-shadow:0 10px 22px color-mix(in srgb,var(--doc-accent) 14%,transparent)}.doc-example__banner{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;padding:16px;border-radius:14px;background:linear-gradient(130deg,color-mix(in srgb,var(--doc-accent) 22%,#10141a),color-mix(in srgb,var(--doc-accent) 10%,#1e2630));color:#f7fbff}.doc-example__banner-copy h2{margin:0 0 6px;font-size:1.35rem;line-height:1.2}.doc-example__banner-copy p{margin:0;color:color-mix(in srgb,#f7fbff 90%,transparent)}.doc-example__banner-art{align-self:center;justify-self:end}.doc-example__summary{display:flex;justify-content:space-between;gap:10px;align-items:flex-start;flex-wrap:wrap}.doc-example__summary-main{display:grid;gap:4px}.doc-example__summary-main h3{margin:0;font-size:1.1rem}.doc-example__summary-main p{margin:0;color:var(--md-sys-color-on-surface-variant, #454e59)}.badge{width:fit-content;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.badge--level{background:color-mix(in srgb,var(--doc-accent) 14%,#ffffff);color:color-mix(in srgb,var(--doc-accent) 86%,#0f151b);border:1px solid color-mix(in srgb,var(--doc-accent) 40%,#cfd6dc)}.mode-toggle{min-height:36px;border-radius:10px;border:1px solid color-mix(in srgb,var(--doc-accent) 44%,#cad2d8);background:color-mix(in srgb,var(--doc-accent) 12%,#ffffff);color:color-mix(in srgb,var(--doc-accent) 84%,#182128);font-weight:600;padding:0 12px;cursor:pointer}.mode-toggle:focus-visible,.doc-example__tab:focus-visible,.copy-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 72%,#4d5b66);outline-offset:2px}.doc-example__tabs{display:flex;flex-wrap:wrap;gap:8px}.doc-example__tab{min-height:34px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--doc-accent) 30%,#cfd6dc);background:color-mix(in srgb,var(--doc-accent) 7%,#ffffff);color:var(--md-sys-color-on-surface, #171b21);font-weight:600;cursor:pointer}.doc-example__tab.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#8fa3b0);background:color-mix(in srgb,var(--doc-accent) 78%,#1a2732);color:#f4fbff}.doc-example__panel{border-radius:14px;border:1px solid color-mix(in srgb,var(--doc-accent) 24%,#d2d9de);background:color-mix(in srgb,var(--doc-accent) 5%,#ffffff);padding:14px}.doc-example__live{min-height:80px}.doc-example__code-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:10px}.doc-example__code-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant, #4f5861)}.copy-btn{min-height:30px;padding:0 10px;border-radius:8px;border:1px solid color-mix(in srgb,var(--doc-accent) 28%,#ccd3d8);background:#fff;cursor:pointer}.copy-btn:disabled{opacity:.6;cursor:not-allowed}.copy-status{color:color-mix(in srgb,var(--doc-accent) 84%,#1f2931);font-size:12px}.doc-example__code{margin:0;max-height:360px;overflow:auto;border-radius:10px;border:1px solid color-mix(in srgb,var(--doc-accent) 22%,#d3dbe0);background:#0f1218;color:#e9eef8;padding:12px;font-size:13px;line-height:1.55}.doc-example__callouts{display:grid;gap:10px}.callout{margin:0;padding:12px 14px;border-radius:10px;border-left:4px solid}.callout--important{border-left-color:#ff8f8f;background:#fff4f4}.callout--note{border-left-color:#91b3ff;background:#f1f6ff}.callout--tip{border-left-color:#84d8bf;background:#ecfff8}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:768px){.doc-example{padding:14px}.doc-example__banner{grid-template-columns:1fr}.doc-example__banner-art{justify-self:start}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5104
5815
|
}
|
|
5105
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5816
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormDocExampleComponent, decorators: [{
|
|
5106
5817
|
type: Component,
|
|
5107
|
-
args: [{ selector: 'praxis-manual-form-doc-example', standalone: true, imports: [
|
|
5818
|
+
args: [{ selector: 'praxis-manual-form-doc-example', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"doc-example\" [attr.data-level]=\"level()\">\n @if (bannerTitle() || bannerDescription()) {\n <header class=\"doc-example__banner\">\n <div class=\"doc-example__banner-copy\">\n @if (bannerTitle()) {\n <h2>{{ bannerTitle() }}</h2>\n }\n @if (bannerDescription()) {\n <p>{{ bannerDescription() }}</p>\n }\n </div>\n <div class=\"doc-example__banner-art\">\n <ng-content select=\"[exampleBannerArtwork]\"></ng-content>\n </div>\n </header>\n }\n\n <div class=\"doc-example__summary\">\n <div class=\"doc-example__summary-main\">\n <span class=\"badge badge--level\">{{ level() }}</span>\n <h3>{{ title() }}</h3>\n @if (subtitle()) {\n <p>{{ subtitle() }}</p>\n }\n </div>\n\n @if (showCustomizationToggle()) {\n <button\n type=\"button\"\n class=\"mode-toggle\"\n [attr.aria-pressed]=\"customizationEnabled()\"\n [attr.aria-label]=\"customizationEnabled() ? 'Desligar modo de customizacao' : 'Ligar modo de customizacao'\"\n (click)=\"toggleCustomization()\"\n >\n {{ customizationEnabled() ? 'Customizacao: ligada' : 'Customizacao: desligada' }}\n </button>\n }\n </div>\n\n <p class=\"sr-only\" [attr.id]=\"idPrefix + '-tabs-help'\">\n Escolha entre visualizacao live, template, TypeScript ou config do exemplo.\n </p>\n\n <div class=\"doc-example__tabs\" role=\"tablist\" [attr.aria-describedby]=\"idPrefix + '-tabs-help'\">\n @for (tab of tabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"doc-example__tab\"\n [class.is-active]=\"activeTab() === tab.id\"\n [attr.id]=\"tabId(tab.id)\"\n [attr.aria-controls]=\"panelId(tab.id)\"\n [attr.aria-selected]=\"activeTab() === tab.id\"\n [attr.aria-label]=\"tab.label + ': ' + tab.hint\"\n (click)=\"setTab(tab.id)\"\n >\n {{ tab.label }}\n </button>\n }\n </div>\n\n <section\n class=\"doc-example__panel\"\n role=\"tabpanel\"\n [attr.id]=\"panelId(activeTab())\"\n [attr.aria-labelledby]=\"tabId(activeTab())\"\n >\n @if (activeTab() === 'live') {\n <div class=\"doc-example__live\">\n <ng-content select=\"[exampleLive]\"></ng-content>\n </div>\n } @else {\n <div class=\"doc-example__code-toolbar\">\n <span class=\"doc-example__code-label\">{{ selectedSnippetLabel() }}</span>\n <button type=\"button\" class=\"copy-btn\" [disabled]=\"!canCopySnippet()\" (click)=\"copyActiveSnippet()\">\n Copiar\n </button>\n @if (copyStatus()) {\n <span class=\"copy-status\" aria-live=\"polite\">{{ copyStatus() }}</span>\n }\n </div>\n <pre class=\"doc-example__code\"><code>{{ selectedSnippet() }}</code></pre>\n }\n </section>\n\n <ng-content select=\"[exampleDiagram]\"></ng-content>\n\n @if (important() || note() || tip()) {\n <div class=\"doc-example__callouts\">\n @if (important()) {\n <p class=\"callout callout--important\"><strong>IMPORTANTE:</strong> {{ important() }}</p>\n }\n @if (note()) {\n <p class=\"callout callout--note\"><strong>NOTA:</strong> {{ note() }}</p>\n }\n @if (tip()) {\n <p class=\"callout callout--tip\"><strong>DICA:</strong> {{ tip() }}</p>\n }\n </div>\n }\n</section>\n", styles: [":host{display:block}.doc-example{--doc-accent: #007a6f;--doc-surface: var(--md-sys-color-surface, #fff);--doc-outline: color-mix(in srgb, var(--doc-accent) 30%, #d6dde1);display:grid;gap:16px;padding:18px;border-radius:18px;border:1px solid var(--doc-outline);background:radial-gradient(140% 120% at 0% 0%,color-mix(in srgb,var(--doc-accent) 10%,transparent),transparent 55%),var(--doc-surface);box-shadow:0 10px 22px color-mix(in srgb,var(--doc-accent) 14%,transparent)}.doc-example__banner{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;padding:16px;border-radius:14px;background:linear-gradient(130deg,color-mix(in srgb,var(--doc-accent) 22%,#10141a),color-mix(in srgb,var(--doc-accent) 10%,#1e2630));color:#f7fbff}.doc-example__banner-copy h2{margin:0 0 6px;font-size:1.35rem;line-height:1.2}.doc-example__banner-copy p{margin:0;color:color-mix(in srgb,#f7fbff 90%,transparent)}.doc-example__banner-art{align-self:center;justify-self:end}.doc-example__summary{display:flex;justify-content:space-between;gap:10px;align-items:flex-start;flex-wrap:wrap}.doc-example__summary-main{display:grid;gap:4px}.doc-example__summary-main h3{margin:0;font-size:1.1rem}.doc-example__summary-main p{margin:0;color:var(--md-sys-color-on-surface-variant, #454e59)}.badge{width:fit-content;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}.badge--level{background:color-mix(in srgb,var(--doc-accent) 14%,#ffffff);color:color-mix(in srgb,var(--doc-accent) 86%,#0f151b);border:1px solid color-mix(in srgb,var(--doc-accent) 40%,#cfd6dc)}.mode-toggle{min-height:36px;border-radius:10px;border:1px solid color-mix(in srgb,var(--doc-accent) 44%,#cad2d8);background:color-mix(in srgb,var(--doc-accent) 12%,#ffffff);color:color-mix(in srgb,var(--doc-accent) 84%,#182128);font-weight:600;padding:0 12px;cursor:pointer}.mode-toggle:focus-visible,.doc-example__tab:focus-visible,.copy-btn:focus-visible{outline:2px solid color-mix(in srgb,var(--doc-accent) 72%,#4d5b66);outline-offset:2px}.doc-example__tabs{display:flex;flex-wrap:wrap;gap:8px}.doc-example__tab{min-height:34px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--doc-accent) 30%,#cfd6dc);background:color-mix(in srgb,var(--doc-accent) 7%,#ffffff);color:var(--md-sys-color-on-surface, #171b21);font-weight:600;cursor:pointer}.doc-example__tab.is-active{border-color:color-mix(in srgb,var(--doc-accent) 62%,#8fa3b0);background:color-mix(in srgb,var(--doc-accent) 78%,#1a2732);color:#f4fbff}.doc-example__panel{border-radius:14px;border:1px solid color-mix(in srgb,var(--doc-accent) 24%,#d2d9de);background:color-mix(in srgb,var(--doc-accent) 5%,#ffffff);padding:14px}.doc-example__live{min-height:80px}.doc-example__code-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:10px}.doc-example__code-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant, #4f5861)}.copy-btn{min-height:30px;padding:0 10px;border-radius:8px;border:1px solid color-mix(in srgb,var(--doc-accent) 28%,#ccd3d8);background:#fff;cursor:pointer}.copy-btn:disabled{opacity:.6;cursor:not-allowed}.copy-status{color:color-mix(in srgb,var(--doc-accent) 84%,#1f2931);font-size:12px}.doc-example__code{margin:0;max-height:360px;overflow:auto;border-radius:10px;border:1px solid color-mix(in srgb,var(--doc-accent) 22%,#d3dbe0);background:#0f1218;color:#e9eef8;padding:12px;font-size:13px;line-height:1.55}.doc-example__callouts{display:grid;gap:10px}.callout{margin:0;padding:12px 14px;border-radius:10px;border-left:4px solid}.callout--important{border-left-color:#ff8f8f;background:#fff4f4}.callout--note{border-left-color:#91b3ff;background:#f1f6ff}.callout--tip{border-left-color:#84d8bf;background:#ecfff8}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}@media(max-width:768px){.doc-example{padding:14px}.doc-example__banner{grid-template-columns:1fr}.doc-example__banner-art{justify-self:start}}\n"] }]
|
|
5108
5819
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], bannerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "bannerTitle", required: false }] }], bannerDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "bannerDescription", required: false }] }], templateCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateCode", required: false }] }], tsCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "tsCode", required: false }] }], configCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "configCode", required: false }] }], customizationEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "customizationEnabled", required: false }] }], showCustomizationToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCustomizationToggle", required: false }] }], important: [{ type: i0.Input, args: [{ isSignal: true, alias: "important", required: false }] }], note: [{ type: i0.Input, args: [{ isSignal: true, alias: "note", required: false }] }], tip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tip", required: false }] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], customizationEnabledChange: [{ type: i0.Output, args: ["customizationEnabledChange"] }], codeCopied: [{ type: i0.Output, args: ["codeCopied"] }] } });
|
|
5109
5820
|
|
|
5110
5821
|
class DocExampleMemoryStorage {
|
|
@@ -5122,7 +5833,7 @@ class DocExampleMemoryStorage {
|
|
|
5122
5833
|
}
|
|
5123
5834
|
}
|
|
5124
5835
|
class ManualFormDocExampleShowcaseComponent {
|
|
5125
|
-
customizationEnabled = signal(false, ...(ngDevMode ? [{ debugName: "customizationEnabled" }] : []));
|
|
5836
|
+
customizationEnabled = signal(false, ...(ngDevMode ? [{ debugName: "customizationEnabled" }] : /* istanbul ignore next */ []));
|
|
5126
5837
|
form = new FormGroup({
|
|
5127
5838
|
nome: new FormControl('', { nonNullable: true, validators: [Validators.required] }),
|
|
5128
5839
|
descricao: new FormControl('', { nonNullable: true }),
|
|
@@ -5157,8 +5868,8 @@ setCustomizationEnabled(enabled: boolean): void {
|
|
|
5157
5868
|
setCustomizationEnabled(enabled) {
|
|
5158
5869
|
this.customizationEnabled.set(enabled);
|
|
5159
5870
|
}
|
|
5160
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5161
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
5871
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormDocExampleShowcaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5872
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: ManualFormDocExampleShowcaseComponent, isStandalone: true, selector: "praxis-manual-form-doc-example-showcase", providers: [
|
|
5162
5873
|
{ provide: API_URL, useValue: { default: { baseUrl: '/api' } } },
|
|
5163
5874
|
{ provide: ASYNC_CONFIG_STORAGE, useFactory: () => new DocExampleMemoryStorage() },
|
|
5164
5875
|
], ngImport: i0, template: `
|
|
@@ -5217,11 +5928,11 @@ setCustomizationEnabled(enabled: boolean): void {
|
|
|
5217
5928
|
</ol>
|
|
5218
5929
|
</div>
|
|
5219
5930
|
</praxis-manual-form-doc-example>
|
|
5220
|
-
`, isInline: true, styles: [":host{display:block}.showcase-art{display:flex;gap:6px;flex-wrap:wrap}.showcase-art__chip{border-radius:999px;padding:4px 8px;font-size:11px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #98a3af) 50%,#d7dde3);background:color-mix(in srgb,var(--md-sys-color-primary, #00796b) 14%,#ffffff);color:var(--md-sys-color-on-surface, #151b22)}.showcase-live{display:grid;gap:12px}.showcase-mode{margin:0;border-radius:10px;border:1px solid #d6dde4;background:#f6f8fb;padding:8px 10px;color:#3b4651;font-size:13px}.showcase-mode--enabled{border-color:#5ebdb0;background:#e9f9f5;color:#075146}.showcase-field{display:grid;gap:6px}.showcase-field span{font-size:13px;font-weight:600}.showcase-field input,.showcase-field textarea{width:100%;border-radius:8px;border:1px solid #c8d2dc;padding:9px 10px;font:inherit;color:#1a222b;background:#fff}.showcase-field input:focus-visible,.showcase-field textarea:focus-visible{outline:2px solid #2d7f73;outline-offset:1px}.showcase-diagram{border-radius:12px;border:1px dashed #bdd0db;background:#f8fbff;padding:12px 14px}.showcase-diagram ol{margin:0;padding-left:20px;display:grid;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type:
|
|
5931
|
+
`, isInline: true, styles: [":host{display:block}.showcase-art{display:flex;gap:6px;flex-wrap:wrap}.showcase-art__chip{border-radius:999px;padding:4px 8px;font-size:11px;font-weight:700;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #98a3af) 50%,#d7dde3);background:color-mix(in srgb,var(--md-sys-color-primary, #00796b) 14%,#ffffff);color:var(--md-sys-color-on-surface, #151b22)}.showcase-live{display:grid;gap:12px}.showcase-mode{margin:0;border-radius:10px;border:1px solid #d6dde4;background:#f6f8fb;padding:8px 10px;color:#3b4651;font-size:13px}.showcase-mode--enabled{border-color:#5ebdb0;background:#e9f9f5;color:#075146}.showcase-field{display:grid;gap:6px}.showcase-field span{font-size:13px;font-weight:600}.showcase-field input,.showcase-field textarea{width:100%;border-radius:8px;border:1px solid #c8d2dc;padding:9px 10px;font:inherit;color:#1a222b;background:#fff}.showcase-field input:focus-visible,.showcase-field textarea:focus-visible{outline:2px solid #2d7f73;outline-offset:1px}.showcase-diagram{border-radius:12px;border:1px dashed #bdd0db;background:#f8fbff;padding:12px 14px}.showcase-diagram ol{margin:0;padding-left:20px;display:grid;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: ManualFormComponent, selector: "praxis-manual-form", inputs: ["formId", "formTitle", "formDescription", "actions", "showHeader", "showActions", "enableAutoSave", "componentInstanceId", "enableCustomization", "persistenceOptions", "usePathNames", "autoSaveDebounceMs"], outputs: ["submitted", "saved", "reset", "metadataChange"] }, { kind: "component", type: ManualFormDocExampleComponent, selector: "praxis-manual-form-doc-example", inputs: ["title", "subtitle", "level", "bannerTitle", "bannerDescription", "templateCode", "tsCode", "configCode", "customizationEnabled", "showCustomizationToggle", "important", "note", "tip"], outputs: ["tabChange", "customizationEnabledChange", "codeCopied"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5221
5932
|
}
|
|
5222
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5933
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormDocExampleShowcaseComponent, decorators: [{
|
|
5223
5934
|
type: Component,
|
|
5224
|
-
args: [{ selector: 'praxis-manual-form-doc-example-showcase', standalone: true, imports: [
|
|
5935
|
+
args: [{ selector: 'praxis-manual-form-doc-example-showcase', standalone: true, imports: [ReactiveFormsModule, ManualFormComponent, ManualFormDocExampleComponent], template: `
|
|
5225
5936
|
<praxis-manual-form-doc-example
|
|
5226
5937
|
title="Cadastro de cargo com preview live"
|
|
5227
5938
|
subtitle="Exemplo live com abas para implementação."
|
|
@@ -5310,10 +6021,10 @@ class ManualFieldDirective {
|
|
|
5310
6021
|
};
|
|
5311
6022
|
this.viewContainer.createEmbeddedView(this.templateRef, context);
|
|
5312
6023
|
}
|
|
5313
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5314
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
6024
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
6025
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: ManualFieldDirective, isStandalone: true, selector: "[praxisManualField]", inputs: { fieldName: ["praxisManualField", "fieldName"], instance: ["praxisManualFieldInstance", "instance"] }, usesOnChanges: true, ngImport: i0 });
|
|
5315
6026
|
}
|
|
5316
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6027
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldDirective, decorators: [{
|
|
5317
6028
|
type: Directive,
|
|
5318
6029
|
args: [{
|
|
5319
6030
|
selector: '[praxisManualField]',
|
|
@@ -5342,10 +6053,10 @@ class ManualFieldEditorOnDblclickDirective {
|
|
|
5342
6053
|
return;
|
|
5343
6054
|
this.manualForm?.tryOpenFieldEditor(this.fieldName);
|
|
5344
6055
|
}
|
|
5345
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5346
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
6056
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldEditorOnDblclickDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
6057
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: ManualFieldEditorOnDblclickDirective, isStandalone: true, selector: "[pdxManualEdit]", inputs: { fieldName: ["pdxManualEdit", "fieldName"] }, host: { listeners: { "dblclick": "onDblClick()" } }, ngImport: i0 });
|
|
5347
6058
|
}
|
|
5348
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6059
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFieldEditorOnDblclickDirective, decorators: [{
|
|
5349
6060
|
type: Directive,
|
|
5350
6061
|
args: [{
|
|
5351
6062
|
selector: '[pdxManualEdit]',
|
|
@@ -5359,6 +6070,348 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
5359
6070
|
args: ['dblclick']
|
|
5360
6071
|
}] } });
|
|
5361
6072
|
|
|
6073
|
+
const manualFieldAddSchema = {
|
|
6074
|
+
type: 'object',
|
|
6075
|
+
required: ['fieldName', 'controlType'],
|
|
6076
|
+
properties: {
|
|
6077
|
+
fieldName: { type: 'string' },
|
|
6078
|
+
controlType: { type: 'string' },
|
|
6079
|
+
label: { type: 'string' },
|
|
6080
|
+
required: { type: 'boolean' },
|
|
6081
|
+
sectionId: { type: 'string' },
|
|
6082
|
+
source: { enum: ['manual-template', 'detected-component', 'metadata-bridge'] },
|
|
6083
|
+
delegateFieldMetadataTo: { enum: ['praxis-metadata-editor'] },
|
|
6084
|
+
},
|
|
6085
|
+
};
|
|
6086
|
+
const manualFieldRemoveSchema = {
|
|
6087
|
+
type: 'object',
|
|
6088
|
+
required: ['fieldName'],
|
|
6089
|
+
properties: {
|
|
6090
|
+
fieldName: { type: 'string' },
|
|
6091
|
+
removeFromLayout: { type: 'boolean' },
|
|
6092
|
+
clearPersistedValue: { type: 'boolean' },
|
|
6093
|
+
},
|
|
6094
|
+
};
|
|
6095
|
+
const manualFieldLabelSetSchema = {
|
|
6096
|
+
type: 'object',
|
|
6097
|
+
required: ['fieldName', 'label'],
|
|
6098
|
+
properties: {
|
|
6099
|
+
fieldName: { type: 'string' },
|
|
6100
|
+
label: { type: 'string' },
|
|
6101
|
+
updatePlaceholderWhenEmpty: { type: 'boolean' },
|
|
6102
|
+
},
|
|
6103
|
+
};
|
|
6104
|
+
const layoutConfigureSchema = {
|
|
6105
|
+
type: 'object',
|
|
6106
|
+
minProperties: 1,
|
|
6107
|
+
properties: {
|
|
6108
|
+
usePathNames: { type: 'boolean' },
|
|
6109
|
+
sections: { type: 'array' },
|
|
6110
|
+
rows: { type: 'array' },
|
|
6111
|
+
columns: { type: 'array' },
|
|
6112
|
+
fieldOrder: {
|
|
6113
|
+
type: 'array',
|
|
6114
|
+
items: { type: 'string' },
|
|
6115
|
+
},
|
|
6116
|
+
delegateAdvancedFormConfigTo: { enum: ['praxis-dynamic-form'] },
|
|
6117
|
+
},
|
|
6118
|
+
};
|
|
6119
|
+
const toolbarConfigureSchema = {
|
|
6120
|
+
type: 'object',
|
|
6121
|
+
minProperties: 1,
|
|
6122
|
+
properties: {
|
|
6123
|
+
enableCustomization: { type: 'boolean' },
|
|
6124
|
+
editableFlags: {
|
|
6125
|
+
type: 'array',
|
|
6126
|
+
items: { enum: ['required', 'readOnly', 'hidden', 'disabled', 'openMetadataEditor'] },
|
|
6127
|
+
},
|
|
6128
|
+
},
|
|
6129
|
+
};
|
|
6130
|
+
const autosaveEnabledSetSchema = {
|
|
6131
|
+
type: 'object',
|
|
6132
|
+
required: ['enabled'],
|
|
6133
|
+
properties: {
|
|
6134
|
+
enabled: { type: 'boolean' },
|
|
6135
|
+
debounceMs: { type: 'number' },
|
|
6136
|
+
storageKey: { type: 'string' },
|
|
6137
|
+
namespace: { type: 'string' },
|
|
6138
|
+
tenantId: { type: 'string' },
|
|
6139
|
+
profileId: { type: 'string' },
|
|
6140
|
+
},
|
|
6141
|
+
};
|
|
6142
|
+
const submitBehaviorSetSchema = {
|
|
6143
|
+
type: 'object',
|
|
6144
|
+
minProperties: 1,
|
|
6145
|
+
properties: {
|
|
6146
|
+
action: { enum: ['submit', 'saveDraft', 'reset', 'cancel', 'custom'] },
|
|
6147
|
+
clearAfterSave: { type: 'boolean' },
|
|
6148
|
+
focusFirstError: { type: 'boolean' },
|
|
6149
|
+
scrollToErrors: { type: 'boolean' },
|
|
6150
|
+
confirmOnUnsavedChanges: { type: 'boolean' },
|
|
6151
|
+
delegateFormSubmitTo: { enum: ['praxis-dynamic-form'] },
|
|
6152
|
+
},
|
|
6153
|
+
};
|
|
6154
|
+
const metadataBridgeConfigureSchema = {
|
|
6155
|
+
type: 'object',
|
|
6156
|
+
minProperties: 1,
|
|
6157
|
+
properties: {
|
|
6158
|
+
enabled: { type: 'boolean' },
|
|
6159
|
+
fieldName: { type: 'string' },
|
|
6160
|
+
openMode: { enum: ['field-toolbar', 'double-click', 'programmatic'] },
|
|
6161
|
+
persistDraftAfterPatch: { type: 'boolean' },
|
|
6162
|
+
delegateFieldMetadataTo: { enum: ['praxis-metadata-editor'] },
|
|
6163
|
+
delegateControlDiscoveryTo: { enum: ['praxis-dynamic-fields'] },
|
|
6164
|
+
},
|
|
6165
|
+
};
|
|
6166
|
+
const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST = {
|
|
6167
|
+
schemaVersion: '1.0.0',
|
|
6168
|
+
componentId: 'praxis-manual-form',
|
|
6169
|
+
ownerPackage: '@praxisui/manual-form',
|
|
6170
|
+
configSchemaId: 'ManualFormInstance',
|
|
6171
|
+
manifestVersion: '1.0.0',
|
|
6172
|
+
runtimeInputs: [
|
|
6173
|
+
{ name: 'formId', type: 'string', description: 'Required manual form id used for runtime state and persistence key composition.' },
|
|
6174
|
+
{ name: 'formGroup', type: 'FormGroup | null', description: 'Host-owned typed FormGroup adopted by the manual form runtime when provided.' },
|
|
6175
|
+
{ name: 'formTitle', type: 'string | null', description: 'Manual form title override.' },
|
|
6176
|
+
{ name: 'formDescription', type: 'string | null', description: 'Manual form description override.' },
|
|
6177
|
+
{ name: 'actions', type: 'FormActionsLayout | null', description: 'Manual toolbar/actions layout.' },
|
|
6178
|
+
{ name: 'enableAutoSave', type: 'boolean', description: 'Enables draft persistence through ManualFormInstance.saveDraft.' },
|
|
6179
|
+
{ name: 'autoSaveDebounceMs', type: 'number', description: 'Autosave debounce in milliseconds.' },
|
|
6180
|
+
{ name: 'enableCustomization', type: 'boolean', description: 'Enables field toolbar and metadata editor bridge.' },
|
|
6181
|
+
{ name: 'persistenceOptions', type: 'ManualFormPersistenceOptions | null', description: 'Namespace, tenant, profile, locale and storage key controls.' },
|
|
6182
|
+
{ name: 'usePathNames', type: 'boolean', description: 'Uses FormControlName.path as FieldMetadata.name for nested manual forms.' },
|
|
6183
|
+
],
|
|
6184
|
+
editableTargets: [
|
|
6185
|
+
{ kind: 'manualField', resolver: 'manual-form-field-by-name', description: 'Detected or declared manual field tracked by ManualFormInstance field metadata.' },
|
|
6186
|
+
{ kind: 'layout', resolver: 'manual-form-layout', description: 'Manual layout ownership: host template layout plus optional FormConfig sections for authored structure.' },
|
|
6187
|
+
{ kind: 'toolbar', resolver: 'manual-form-customization-toolbar', description: 'Customization toolbar and quick metadata toggles.' },
|
|
6188
|
+
{ kind: 'autosave', resolver: 'manual-form-autosave-policy', description: 'Autosave enablement, debounce and persistence key controls.' },
|
|
6189
|
+
{ kind: 'metadataBridge', resolver: 'manual-field-metadata-bridge', description: 'Bridge from manual fields to @praxisui/metadata-editor patches.' },
|
|
6190
|
+
{ kind: 'submitBehavior', resolver: 'manual-form-submit-behavior', description: 'Submit, reset, validation focus and unsaved-change behavior.' },
|
|
6191
|
+
],
|
|
6192
|
+
operations: [
|
|
6193
|
+
{
|
|
6194
|
+
operationId: 'manualField.add',
|
|
6195
|
+
title: 'Add manual field metadata',
|
|
6196
|
+
scope: 'field',
|
|
6197
|
+
targetKind: 'manualField',
|
|
6198
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
6199
|
+
inputSchema: manualFieldAddSchema,
|
|
6200
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-add', handlerContract: {
|
|
6201
|
+
reads: ['ManualFormInstance.currentConfig', 'ManualFormInstance.currentFieldMetadata', 'ManualFieldKeyService', 'dynamic-fields-control-discovery'],
|
|
6202
|
+
writes: ['currentConfig.fieldMetadata', 'currentFieldMetadata', 'form'],
|
|
6203
|
+
identityKeys: ['fieldName'],
|
|
6204
|
+
inputSchema: manualFieldAddSchema,
|
|
6205
|
+
failureModes: ['duplicate-manual-field-id', 'control-type-not-discovered', 'host-template-field-missing', 'field-metadata-delegation-required'],
|
|
6206
|
+
description: 'Adds metadata for a manual field while preserving host-owned template layout and delegating advanced FieldMetadata edits.',
|
|
6207
|
+
} }],
|
|
6208
|
+
validators: ['manual-field-id-unique', 'control-type-discovered', 'host-template-field-exists', 'metadata-bridge-does-not-redefine-schema', 'manual-form-round-trip'],
|
|
6209
|
+
affectedPaths: ['currentConfig.fieldMetadata', 'currentFieldMetadata', 'form'],
|
|
6210
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
6211
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6212
|
+
destructive: false,
|
|
6213
|
+
requiresConfirmation: false,
|
|
6214
|
+
},
|
|
6215
|
+
{
|
|
6216
|
+
operationId: 'manualField.remove',
|
|
6217
|
+
title: 'Remove manual field metadata',
|
|
6218
|
+
scope: 'field',
|
|
6219
|
+
targetKind: 'manualField',
|
|
6220
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
6221
|
+
inputSchema: manualFieldRemoveSchema,
|
|
6222
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-remove', handlerContract: {
|
|
6223
|
+
reads: ['ManualFormInstance.currentConfig', 'ManualFormInstance.currentFieldMetadata', 'ManualFormInstance.form', 'FormConfig.sections'],
|
|
6224
|
+
writes: ['currentConfig.fieldMetadata', 'currentConfig.sections', 'currentFieldMetadata', 'form'],
|
|
6225
|
+
identityKeys: ['fieldName'],
|
|
6226
|
+
inputSchema: manualFieldRemoveSchema,
|
|
6227
|
+
failureModes: ['manual-field-not-found', 'field-still-referenced-by-layout', 'persisted-value-removal-not-confirmed'],
|
|
6228
|
+
description: 'Removes a manual field by stable field name and requires explicit confirmation before metadata, layout or value loss.',
|
|
6229
|
+
} }],
|
|
6230
|
+
destructive: true,
|
|
6231
|
+
requiresConfirmation: true,
|
|
6232
|
+
validators: ['manual-field-exists', 'field-removal-confirmed', 'layout-field-references-valid', 'manual-form-round-trip'],
|
|
6233
|
+
affectedPaths: ['currentConfig.fieldMetadata', 'currentConfig.sections', 'currentFieldMetadata', 'form'],
|
|
6234
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
6235
|
+
preconditions: ['manual-form-instance-loaded', 'explicit-confirmation-provided'],
|
|
6236
|
+
},
|
|
6237
|
+
{
|
|
6238
|
+
operationId: 'manualField.label.set',
|
|
6239
|
+
title: 'Set manual field label',
|
|
6240
|
+
scope: 'field',
|
|
6241
|
+
targetKind: 'manualField',
|
|
6242
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
6243
|
+
inputSchema: manualFieldLabelSetSchema,
|
|
6244
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-label-set', handlerContract: {
|
|
6245
|
+
reads: ['ManualFormInstance.currentFieldMetadata', 'ManualFieldMetadataBridgeService'],
|
|
6246
|
+
writes: ['currentConfig.fieldMetadata[].label', 'currentConfig.fieldMetadata[].placeholder', 'currentFieldMetadata'],
|
|
6247
|
+
identityKeys: ['fieldName'],
|
|
6248
|
+
inputSchema: manualFieldLabelSetSchema,
|
|
6249
|
+
failureModes: ['manual-field-not-found', 'label-empty', 'metadata-patch-rejected'],
|
|
6250
|
+
description: 'Sets a manual field label through the metadata bridge without redefining backend schema semantics.',
|
|
6251
|
+
} }],
|
|
6252
|
+
validators: ['manual-field-exists', 'field-label-valid', 'metadata-bridge-does-not-redefine-schema', 'manual-form-round-trip'],
|
|
6253
|
+
affectedPaths: ['currentConfig.fieldMetadata[].label', 'currentConfig.fieldMetadata[].placeholder', 'currentFieldMetadata'],
|
|
6254
|
+
submissionImpact: 'visual-only',
|
|
6255
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6256
|
+
destructive: false,
|
|
6257
|
+
requiresConfirmation: false,
|
|
6258
|
+
},
|
|
6259
|
+
{
|
|
6260
|
+
operationId: 'layout.configure',
|
|
6261
|
+
title: 'Configure manual form layout',
|
|
6262
|
+
scope: 'layout',
|
|
6263
|
+
targetKind: 'layout',
|
|
6264
|
+
target: { kind: 'layout', resolver: 'manual-form-layout', ambiguityPolicy: 'fail', required: false },
|
|
6265
|
+
inputSchema: layoutConfigureSchema,
|
|
6266
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-layout-configure', handlerContract: {
|
|
6267
|
+
reads: ['ManualFormInstance.currentConfig', 'FormConfig.sections', 'host-template-layout', 'praxis-dynamic-form-authoring-manifest'],
|
|
6268
|
+
writes: ['currentConfig.sections', 'usePathNames'],
|
|
6269
|
+
identityKeys: ['sectionId', 'rowId', 'columnId', 'fieldName'],
|
|
6270
|
+
inputSchema: layoutConfigureSchema,
|
|
6271
|
+
failureModes: ['layout-field-reference-missing', 'advanced-form-config-delegation-required', 'host-template-layout-conflict'],
|
|
6272
|
+
description: 'Configures manual layout metadata and delegates advanced FormConfig layout semantics to the dynamic-form manifest.',
|
|
6273
|
+
} }],
|
|
6274
|
+
validators: ['layout-field-references-valid', 'manual-layout-does-not-replace-host-template', 'delegates-form-config', 'manual-form-round-trip'],
|
|
6275
|
+
affectedPaths: ['currentConfig.sections', 'usePathNames'],
|
|
6276
|
+
submissionImpact: 'config-only',
|
|
6277
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6278
|
+
destructive: false,
|
|
6279
|
+
requiresConfirmation: false,
|
|
6280
|
+
},
|
|
6281
|
+
{
|
|
6282
|
+
operationId: 'toolbar.configure',
|
|
6283
|
+
title: 'Configure manual form customization toolbar',
|
|
6284
|
+
scope: 'toolbarUi',
|
|
6285
|
+
targetKind: 'toolbar',
|
|
6286
|
+
target: { kind: 'toolbar', resolver: 'manual-form-customization-toolbar', ambiguityPolicy: 'fail', required: false },
|
|
6287
|
+
inputSchema: toolbarConfigureSchema,
|
|
6288
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-toolbar-configure', handlerContract: {
|
|
6289
|
+
reads: ['ManualFormComponent.enableCustomization', 'ManualFieldToolbarComponent', 'ManualFieldEditorOnDblclickDirective'],
|
|
6290
|
+
writes: ['enableCustomization'],
|
|
6291
|
+
identityKeys: ['formId'],
|
|
6292
|
+
inputSchema: toolbarConfigureSchema,
|
|
6293
|
+
failureModes: ['toolbar-disabled-with-required-bridge', 'unsupported-toolbar-flag'],
|
|
6294
|
+
description: 'Configures the manual customization toolbar and keeps metadata edit entry points behind enableCustomization.',
|
|
6295
|
+
} }],
|
|
6296
|
+
validators: ['toolbar-flags-supported', 'metadata-bridge-gated-by-customization', 'manual-form-round-trip'],
|
|
6297
|
+
affectedPaths: ['enableCustomization'],
|
|
6298
|
+
submissionImpact: 'visual-only',
|
|
6299
|
+
preconditions: ['manual-form-component-loaded'],
|
|
6300
|
+
destructive: false,
|
|
6301
|
+
requiresConfirmation: false,
|
|
6302
|
+
},
|
|
6303
|
+
{
|
|
6304
|
+
operationId: 'autosave.enabled.set',
|
|
6305
|
+
title: 'Set manual form autosave policy',
|
|
6306
|
+
scope: 'interaction',
|
|
6307
|
+
targetKind: 'autosave',
|
|
6308
|
+
target: { kind: 'autosave', resolver: 'manual-form-autosave-policy', ambiguityPolicy: 'fail', required: false },
|
|
6309
|
+
inputSchema: autosaveEnabledSetSchema,
|
|
6310
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-autosave-enabled-set', handlerContract: {
|
|
6311
|
+
reads: ['enableAutoSave', 'autoSaveDebounceMs', 'ManualFormPersistenceOptions', 'ASYNC_CONFIG_STORAGE'],
|
|
6312
|
+
writes: ['enableAutoSave', 'autoSaveDebounceMs', 'persistenceOptions'],
|
|
6313
|
+
identityKeys: ['formId', 'storageKey', 'namespace', 'tenantId', 'profileId'],
|
|
6314
|
+
inputSchema: autosaveEnabledSetSchema,
|
|
6315
|
+
failureModes: ['autosave-storage-missing', 'unsafe-debounce', 'ambiguous-storage-key', 'ssr-storage-not-safe'],
|
|
6316
|
+
description: 'Sets autosave explicitly and requires safe debounce plus deterministic persistence key composition.',
|
|
6317
|
+
} }],
|
|
6318
|
+
validators: ['autosave-explicit', 'autosave-debounce-safe', 'autosave-storage-available', 'persistence-key-deterministic', 'manual-form-round-trip'],
|
|
6319
|
+
affectedPaths: ['enableAutoSave', 'autoSaveDebounceMs', 'persistenceOptions'],
|
|
6320
|
+
submissionImpact: 'config-only',
|
|
6321
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6322
|
+
destructive: false,
|
|
6323
|
+
requiresConfirmation: false,
|
|
6324
|
+
},
|
|
6325
|
+
{
|
|
6326
|
+
operationId: 'submitBehavior.set',
|
|
6327
|
+
title: 'Set manual form submit behavior',
|
|
6328
|
+
scope: 'interaction',
|
|
6329
|
+
targetKind: 'submitBehavior',
|
|
6330
|
+
target: { kind: 'submitBehavior', resolver: 'manual-form-submit-behavior', ambiguityPolicy: 'fail', required: false },
|
|
6331
|
+
inputSchema: submitBehaviorSetSchema,
|
|
6332
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-submit-behavior-set', handlerContract: {
|
|
6333
|
+
reads: ['ManualFormComponent.submitted', 'ManualFormInstance.form', 'FormConfig.behavior', 'praxis-dynamic-form-authoring-manifest'],
|
|
6334
|
+
writes: ['currentConfig.behavior', 'submitted', 'saved', 'resetEvent'],
|
|
6335
|
+
identityKeys: ['formId', 'action'],
|
|
6336
|
+
inputSchema: submitBehaviorSetSchema,
|
|
6337
|
+
failureModes: ['submit-action-unsupported', 'advanced-form-submit-delegation-required', 'validation-focus-target-missing'],
|
|
6338
|
+
description: 'Configures manual submit/reset behavior and delegates dynamic-form submit payload semantics to the dynamic-form manifest.',
|
|
6339
|
+
} }],
|
|
6340
|
+
validators: ['submit-behavior-supported', 'delegates-form-config', 'manual-form-round-trip'],
|
|
6341
|
+
affectedPaths: ['currentConfig.behavior', 'submitted', 'saved', 'resetEvent'],
|
|
6342
|
+
submissionImpact: 'affects-submission',
|
|
6343
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6344
|
+
destructive: false,
|
|
6345
|
+
requiresConfirmation: false,
|
|
6346
|
+
},
|
|
6347
|
+
{
|
|
6348
|
+
operationId: 'metadataBridge.configure',
|
|
6349
|
+
title: 'Configure manual metadata bridge',
|
|
6350
|
+
scope: 'fieldMetadataPath',
|
|
6351
|
+
targetKind: 'metadataBridge',
|
|
6352
|
+
target: { kind: 'metadataBridge', resolver: 'manual-field-metadata-bridge', ambiguityPolicy: 'fail', required: false },
|
|
6353
|
+
inputSchema: metadataBridgeConfigureSchema,
|
|
6354
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-metadata-bridge-configure', handlerContract: {
|
|
6355
|
+
reads: ['ManualFieldMetadataBridgeService', 'SettingsPanelService', 'PRAXIS_METADATA_EDITOR_AUTHORING_MANIFEST', 'dynamic-fields-discovery'],
|
|
6356
|
+
writes: ['enableCustomization', 'currentFieldMetadata', 'currentConfig.fieldMetadata'],
|
|
6357
|
+
identityKeys: ['formId', 'fieldName', 'openMode'],
|
|
6358
|
+
inputSchema: metadataBridgeConfigureSchema,
|
|
6359
|
+
failureModes: ['metadata-editor-unavailable', 'field-metadata-delegation-required', 'control-discovery-delegation-required', 'draft-persistence-failed'],
|
|
6360
|
+
description: 'Configures the bridge that opens metadata-editor for manual fields and persists accepted patches through ManualFormInstance.',
|
|
6361
|
+
} }],
|
|
6362
|
+
validators: ['metadata-bridge-does-not-redefine-schema', 'delegates-field-metadata', 'control-type-discovered', 'metadata-bridge-gated-by-customization', 'manual-form-round-trip'],
|
|
6363
|
+
affectedPaths: ['enableCustomization', 'currentFieldMetadata', 'currentConfig.fieldMetadata'],
|
|
6364
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
6365
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
6366
|
+
destructive: false,
|
|
6367
|
+
requiresConfirmation: false,
|
|
6368
|
+
},
|
|
6369
|
+
],
|
|
6370
|
+
validators: [
|
|
6371
|
+
{ validatorId: 'manual-field-id-unique', level: 'error', code: 'MANUAL_FORM_FIELD_ID_UNIQUE', description: 'Manual field names must be unique in the instance metadata map.' },
|
|
6372
|
+
{ validatorId: 'manual-field-exists', level: 'error', code: 'MANUAL_FORM_FIELD_EXISTS', description: 'Target manual field must exist before patching or removing it.' },
|
|
6373
|
+
{ validatorId: 'field-removal-confirmed', level: 'error', code: 'MANUAL_FORM_FIELD_REMOVAL_CONFIRMED', description: 'Removing a field or its persisted value requires explicit confirmation.' },
|
|
6374
|
+
{ validatorId: 'field-label-valid', level: 'error', code: 'MANUAL_FORM_FIELD_LABEL_VALID', description: 'Manual field label must be a non-empty user-facing string.' },
|
|
6375
|
+
{ validatorId: 'host-template-field-exists', level: 'error', code: 'MANUAL_FORM_HOST_FIELD_EXISTS', description: 'Manual field metadata must correspond to a host template control or declared metadata bridge target.' },
|
|
6376
|
+
{ validatorId: 'control-type-discovered', level: 'error', code: 'MANUAL_FORM_CONTROL_TYPE_DISCOVERED', description: 'Control type must be discovered through dynamic-fields mappings or delegated discovery.' },
|
|
6377
|
+
{ validatorId: 'metadata-bridge-does-not-redefine-schema', level: 'error', code: 'MANUAL_FORM_METADATA_BRIDGE_SCHEMA_SAFE', description: 'Metadata bridge patches must not silently redefine backend schema or schema-driven FormConfig semantics.' },
|
|
6378
|
+
{ validatorId: 'delegates-field-metadata', level: 'error', code: 'MANUAL_FORM_DELEGATES_FIELD_METADATA', description: 'Advanced FieldMetadata edits must be delegated to the metadata-editor manifest.' },
|
|
6379
|
+
{ validatorId: 'delegates-form-config', level: 'error', code: 'MANUAL_FORM_DELEGATES_FORM_CONFIG', description: 'Advanced FormConfig semantics must be delegated to the dynamic-form manifest.' },
|
|
6380
|
+
{ validatorId: 'layout-field-references-valid', level: 'error', code: 'MANUAL_FORM_LAYOUT_FIELD_REFERENCES_VALID', description: 'Layout field references must resolve to manual fields.' },
|
|
6381
|
+
{ validatorId: 'manual-layout-does-not-replace-host-template', level: 'error', code: 'MANUAL_FORM_LAYOUT_HOST_TEMPLATE_SAFE', description: 'Manual layout metadata must not pretend to rewrite host-owned HTML template structure.' },
|
|
6382
|
+
{ validatorId: 'toolbar-flags-supported', level: 'error', code: 'MANUAL_FORM_TOOLBAR_FLAGS_SUPPORTED', description: 'Toolbar quick edit flags must be supported by the manual field toolbar.' },
|
|
6383
|
+
{ validatorId: 'metadata-bridge-gated-by-customization', level: 'error', code: 'MANUAL_FORM_METADATA_BRIDGE_GATED', description: 'Metadata bridge entry points must respect enableCustomization.' },
|
|
6384
|
+
{ validatorId: 'autosave-explicit', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_EXPLICIT', description: 'Autosave enablement and persistence policy must be explicit.' },
|
|
6385
|
+
{ validatorId: 'autosave-debounce-safe', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_DEBOUNCE_SAFE', description: 'Autosave debounce must be positive and safe for storage backends.' },
|
|
6386
|
+
{ validatorId: 'autosave-storage-available', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_STORAGE_AVAILABLE', description: 'Autosave requires a valid AsyncConfigStorage implementation.' },
|
|
6387
|
+
{ validatorId: 'persistence-key-deterministic', level: 'error', code: 'MANUAL_FORM_PERSISTENCE_KEY_DETERMINISTIC', description: 'Persistence key composition must be deterministic across reopen/reload.' },
|
|
6388
|
+
{ validatorId: 'submit-behavior-supported', level: 'error', code: 'MANUAL_FORM_SUBMIT_BEHAVIOR_SUPPORTED', description: 'Submit behavior must map to supported manual form outputs or delegated dynamic-form semantics.' },
|
|
6389
|
+
{ validatorId: 'manual-form-round-trip', level: 'error', code: 'MANUAL_FORM_ROUND_TRIP', description: 'Open, edit, apply/save, reopen and runtime consume must preserve manual form config.' },
|
|
6390
|
+
],
|
|
6391
|
+
roundTripRequirements: [
|
|
6392
|
+
'ManualFormInstance is the package-level runtime document: config, field metadata map, FormGroup and persistence key must remain coherent.',
|
|
6393
|
+
'Manual field ids are stable field names; array indexes are not canonical identity.',
|
|
6394
|
+
'Field removal is destructive and requires confirmation before metadata, layout references or persisted values are removed.',
|
|
6395
|
+
'Autosave must be explicit, have a safe debounce and use deterministic persistence key composition through ManualFormPersistenceOptions.',
|
|
6396
|
+
'The metadata bridge may apply metadata-editor patches but must not silently redefine backend schema or duplicate FieldMetadata semantics.',
|
|
6397
|
+
'Advanced FormConfig authoring belongs to praxis-dynamic-form; this manifest governs manual form orchestration and delegates deeper FormConfig semantics.',
|
|
6398
|
+
],
|
|
6399
|
+
examples: [
|
|
6400
|
+
{ id: 'add-text-field', request: 'Add a manual text field for customer name.', operationId: 'manualField.add', params: { fieldName: 'customerName', controlType: 'input', label: 'Customer name', source: 'manual-template', delegateFieldMetadataTo: 'praxis-metadata-editor' }, isPositive: true },
|
|
6401
|
+
{ id: 'remove-obsolete-field', request: 'Remove the obsolete nickname field from the manual form.', operationId: 'manualField.remove', params: { fieldName: 'nickname', removeFromLayout: true, clearPersistedValue: true }, isPositive: true },
|
|
6402
|
+
{ id: 'rename-label', request: 'Change the label of cpf to CPF/CNPJ.', operationId: 'manualField.label.set', params: { fieldName: 'cpf', label: 'CPF/CNPJ' }, isPositive: true },
|
|
6403
|
+
{ id: 'enable-path-names', request: 'Use nested form paths as field names.', operationId: 'layout.configure', params: { usePathNames: true }, isPositive: true },
|
|
6404
|
+
{ id: 'configure-toolbar', request: 'Enable customization toolbar with required and hidden toggles.', operationId: 'toolbar.configure', params: { enableCustomization: true, editableFlags: ['required', 'hidden', 'openMetadataEditor'] }, isPositive: true },
|
|
6405
|
+
{ id: 'enable-autosave', request: 'Enable autosave every second for this tenant profile.', operationId: 'autosave.enabled.set', params: { enabled: true, debounceMs: 1000, namespace: 'sales', tenantId: 'acme', profileId: 'admin' }, isPositive: true },
|
|
6406
|
+
{ id: 'set-submit-behavior', request: 'Focus the first invalid field and scroll to errors on submit.', operationId: 'submitBehavior.set', params: { action: 'submit', focusFirstError: true, scrollToErrors: true }, isPositive: true },
|
|
6407
|
+
{ id: 'configure-metadata-bridge', request: 'Open metadata editor from the toolbar and persist draft after patch.', operationId: 'metadataBridge.configure', params: { enabled: true, openMode: 'field-toolbar', persistDraftAfterPatch: true, delegateFieldMetadataTo: 'praxis-metadata-editor', delegateControlDiscoveryTo: 'praxis-dynamic-fields' }, isPositive: true },
|
|
6408
|
+
{ id: 'reject-duplicate-field', request: 'Add another customerName field with a different label.', operationId: 'manualField.add', params: { fieldName: 'customerName', controlType: 'input', label: 'Duplicate customer' }, isPositive: false },
|
|
6409
|
+
{ id: 'reject-unconfirmed-removal', request: 'Remove email and clear its saved value without confirmation.', operationId: 'manualField.remove', params: { fieldName: 'email', clearPersistedValue: true }, isPositive: false },
|
|
6410
|
+
{ id: 'reject-unsafe-autosave', request: 'Autosave every millisecond with no storage identity.', operationId: 'autosave.enabled.set', params: { enabled: true, debounceMs: 1 }, isPositive: false },
|
|
6411
|
+
{ id: 'reject-schema-redefinition', request: 'Use manual form metadata bridge to replace the backend schema for cpf.', operationId: 'metadataBridge.configure', params: { enabled: true, fieldName: 'cpf', backendSchemaOverride: { type: 'number' } }, isPositive: false },
|
|
6412
|
+
],
|
|
6413
|
+
};
|
|
6414
|
+
|
|
5362
6415
|
/*
|
|
5363
6416
|
* Public API Surface of praxis-manual-form
|
|
5364
6417
|
*/
|
|
@@ -5367,4 +6420,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
5367
6420
|
* Generated bundle index. Do not edit.
|
|
5368
6421
|
*/
|
|
5369
6422
|
|
|
5370
|
-
export { MANUAL_FORM_AI_CAPABILITIES, MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE, MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, ManualFieldDirective, ManualFieldEditorOnDblclickDirective, ManualFieldKeyService, ManualFieldMetadataBridgeService, ManualFormActionsComponent, ManualFormComponent, ManualFormConfigEditorComponent, ManualFormDocExampleComponent, ManualFormDocExampleShowcaseComponent, ManualFormHeaderComponent, ManualFormInstance, ManualFormInstanceFactory, createManualFormSeed, toFieldMetadataMap };
|
|
6423
|
+
export { MANUAL_FORM_AI_CAPABILITIES, MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE, MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, ManualFieldDirective, ManualFieldEditorOnDblclickDirective, ManualFieldKeyService, ManualFieldMetadataBridgeService, ManualFormActionsComponent, ManualFormComponent, ManualFormConfigEditorComponent, ManualFormDocExampleComponent, ManualFormDocExampleShowcaseComponent, ManualFormHeaderComponent, ManualFormInstance, ManualFormInstanceFactory, PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST, createManualFormSeed, toFieldMetadataMap };
|