@praxisui/manual-form 9.0.0-beta.7 → 9.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.
@@ -1,11 +1,11 @@
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';
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, ComponentMetadataRegistry } from '@praxisui/core';
2
2
  import * as i0 from '@angular/core';
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';
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, ENVIRONMENT_INITIALIZER } from '@angular/core';
4
4
  import { BehaviorSubject, firstValueFrom, debounceTime, fromEvent, of } from 'rxjs';
5
5
  import { take } from 'rxjs/operators';
6
6
  import { ActivatedRoute } from '@angular/router';
7
7
  import { isPlatformBrowser } from '@angular/common';
8
- import { BaseAiAdapter, shouldRoutePromptToGovernedDecision, AiBackendApiService, PraxisAssistantSessionRegistryService, PraxisAssistantTurnOrchestratorService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
8
+ import { BaseAiAdapter, withAuthoringScopePolicy, 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';
@@ -586,13 +586,15 @@ function generateRulePropertyCapabilities(targetType, properties) {
586
586
  properties.forEach((prop) => {
587
587
  const valueKind = prop.type === 'object'
588
588
  ? 'object'
589
- : prop.type === 'enum'
590
- ? 'enum'
591
- : prop.type === 'boolean'
592
- ? 'boolean'
593
- : prop.type === 'number'
594
- ? 'number'
595
- : 'string';
589
+ : prop.type === 'array'
590
+ ? 'array'
591
+ : prop.type === 'enum'
592
+ ? 'enum'
593
+ : prop.type === 'boolean'
594
+ ? 'boolean'
595
+ : prop.type === 'number'
596
+ ? 'number'
597
+ : 'string';
596
598
  const capability = {
597
599
  path: `formRules[].effect.properties.${prop.name}`,
598
600
  category: 'rules',
@@ -605,7 +607,7 @@ function generateRulePropertyCapabilities(targetType, properties) {
605
607
  : prop.type === 'enum'
606
608
  ? (prop.enumValues?.[0]?.value || 'valor')
607
609
  : 'valor',
608
- safetyNotes: prop.type === 'object' ? 'O objeto deve seguir o schema esperado pelo componente alvo.' : undefined,
610
+ safetyNotes: prop.type === 'object' ? 'O objeto deve seguir o schema esperado pelo componente alvo.' : prop.type === 'array' ? 'A lista deve seguir o schema esperado pelo componente alvo.' : undefined,
609
611
  };
610
612
  if (prop.enumValues) {
611
613
  capability.allowedValues = prop.enumValues.map((ev) => ev.value);
@@ -619,13 +621,15 @@ function generateRulePropertyWhenFalseCapabilities(targetType, properties) {
619
621
  properties.forEach((prop) => {
620
622
  const valueKind = prop.type === 'object'
621
623
  ? 'object'
622
- : prop.type === 'enum'
623
- ? 'enum'
624
- : prop.type === 'boolean'
625
- ? 'boolean'
626
- : prop.type === 'number'
627
- ? 'number'
628
- : 'string';
624
+ : prop.type === 'array'
625
+ ? 'array'
626
+ : prop.type === 'enum'
627
+ ? 'enum'
628
+ : prop.type === 'boolean'
629
+ ? 'boolean'
630
+ : prop.type === 'number'
631
+ ? 'number'
632
+ : 'string';
629
633
  const capability = {
630
634
  path: `formRules[].effect.propertiesWhenFalse.${prop.name}`,
631
635
  category: 'rules',
@@ -638,7 +642,7 @@ function generateRulePropertyWhenFalseCapabilities(targetType, properties) {
638
642
  : prop.type === 'enum'
639
643
  ? (prop.enumValues?.[0]?.value || 'valor')
640
644
  : 'valor',
641
- safetyNotes: prop.type === 'object' ? 'O objeto deve seguir o schema esperado pelo componente alvo.' : undefined,
645
+ safetyNotes: prop.type === 'object' ? 'O objeto deve seguir o schema esperado pelo componente alvo.' : prop.type === 'array' ? 'A lista deve seguir o schema esperado pelo componente alvo.' : undefined,
642
646
  };
643
647
  if (prop.enumValues) {
644
648
  capability.allowedValues = prop.enumValues.map((ev) => ev.value);
@@ -1025,7 +1029,13 @@ const MANUAL_FORM_AI_CAPABILITIES = {
1025
1029
  ...generateRulePropertyWhenFalseCapabilities('action', RULE_PROPERTY_SCHEMA.action),
1026
1030
  ...generateRulePropertyWhenFalseCapabilities('row', RULE_PROPERTY_SCHEMA.row),
1027
1031
  ...generateRulePropertyWhenFalseCapabilities('column', RULE_PROPERTY_SCHEMA.column),
1028
- { path: 'formRulesState', category: 'rules', valueKind: 'object', description: 'Estado bruto do visual builder.' },
1032
+ {
1033
+ path: 'formRulesState',
1034
+ category: 'metadata',
1035
+ valueKind: 'object',
1036
+ description: 'Estado interno do builder visual de regras, gerado apenas para round-trip do editor.',
1037
+ safetyNotes: 'Read-only/internal. Nao use como alvo de autoria, patch, exemplo ou operacao de IA; gere somente formRules e deixe o editor materializar formRulesState.',
1038
+ },
1029
1039
  { path: 'hooks', category: 'hooks', valueKind: 'object', description: 'Declaracoes de hooks por estagio.' },
1030
1040
  { path: 'hooks.beforeInit', category: 'hooks', valueKind: 'array', description: 'Hooks beforeInit.' },
1031
1041
  { path: 'hooks.beforeInit[]', category: 'hooks', valueKind: 'array', description: 'Hooks beforeInit.' },
@@ -1251,7 +1261,7 @@ class ManualFormAgenticAuthoringTurnFlow {
1251
1261
  if (this.shouldRouteToGovernedDecision(prompt, contextHints)) {
1252
1262
  return this.toGovernedDecisionHandoff(prompt, request);
1253
1263
  }
1254
- const response = await firstValueFrom(this.aiApi.getPatch({
1264
+ const response = await firstValueFrom(this.aiApi.getPatch(withAuthoringScopePolicy({
1255
1265
  componentId,
1256
1266
  componentType,
1257
1267
  userPrompt: prompt,
@@ -1268,7 +1278,11 @@ class ManualFormAgenticAuthoringTurnFlow {
1268
1278
  ...(runtimeState ? { runtimeState } : {}),
1269
1279
  ...(schemaFields?.length ? { schemaFields } : {}),
1270
1280
  ...(contextHints ? { contextHints } : {}),
1271
- }));
1281
+ }, {
1282
+ componentId,
1283
+ componentType,
1284
+ componentLabel: this.adapter.componentName || 'formulario',
1285
+ })));
1272
1286
  return this.toTurnResult(this.compileAdapterResponse(response), request);
1273
1287
  }
1274
1288
  async apply(_request) {
@@ -3446,10 +3460,11 @@ const MANUAL_FORM_EN_US = {
3446
3460
  'praxis.manualForm.editor.rules.apply': 'Apply rules',
3447
3461
  'praxis.manualForm.editor.rules.note': 'Persisted in config; execution depends on the host.',
3448
3462
  'praxis.manualForm.editor.rules.formRulesLabel': 'formRules (JSON)',
3449
- 'praxis.manualForm.editor.rules.formRulesStateLabel': 'formRulesState (JSON)',
3450
- 'praxis.manualForm.editor.rules.formRulesPlaceholder': '[{"id":"rule-1","name":"Required rule","targetType":"field","targets":["field"],"effect":{"condition":"{field} != null","properties":{"required":true}}}]',
3463
+ 'praxis.manualForm.editor.rules.formRulesStateLabel': 'Visual editor internal state (formRulesState - JSON)',
3464
+ 'praxis.manualForm.editor.rules.formRulesPlaceholder': '[{"id":"rule-1","name":"Required rule","targetType":"field","targets":["field"],"effect":{"condition":{"!==":[{"var":"field"},null]},"properties":{"required":true}}}]',
3451
3465
  'praxis.manualForm.editor.rules.tooltip': 'JSON array with rules (id, targetType, targets, effect).',
3452
- 'praxis.manualForm.editor.rules.stateTooltip': 'Raw state from the visual editor (optional).',
3466
+ 'praxis.manualForm.editor.rules.stateTooltip': 'Read-only internal round-trip state for the visual editor; edit formRules instead.',
3467
+ 'praxis.manualForm.editor.rules.formRulesStateReadonlyHint': 'Generated by the visual editor for round-trip; edit formRules instead.',
3453
3468
  'praxis.manualForm.editor.cascade.title': 'Field dependencies',
3454
3469
  'praxis.manualForm.editor.cascade.help': 'Configure native cascades based on metadata.',
3455
3470
  'praxis.manualForm.editor.cascade.note': 'Changes update metadata and are saved in the draft.',
@@ -3584,10 +3599,11 @@ const MANUAL_FORM_PT_BR = {
3584
3599
  'praxis.manualForm.editor.rules.apply': 'Aplicar regras',
3585
3600
  'praxis.manualForm.editor.rules.note': 'Persistido no config; a execução depende do host.',
3586
3601
  'praxis.manualForm.editor.rules.formRulesLabel': 'Regras do formulário (formRules - JSON)',
3587
- 'praxis.manualForm.editor.rules.formRulesStateLabel': 'Estado das regras (formRulesState - JSON)',
3588
- 'praxis.manualForm.editor.rules.formRulesPlaceholder': '[{"id":"rule-1","name":"Obrigatoriedade","targetType":"field","targets":["campo"],"effect":{"condition":"{campo} != null","properties":{"required":true}}}]',
3602
+ 'praxis.manualForm.editor.rules.formRulesStateLabel': 'Estado interno do editor visual (formRulesState - JSON)',
3603
+ 'praxis.manualForm.editor.rules.formRulesPlaceholder': '[{"id":"rule-1","name":"Obrigatoriedade","targetType":"field","targets":["campo"],"effect":{"condition":{"!==":[{"var":"campo"},null]},"properties":{"required":true}}}]',
3589
3604
  'praxis.manualForm.editor.rules.tooltip': 'Array JSON com regras (id, targetType, targets, effect).',
3590
- 'praxis.manualForm.editor.rules.stateTooltip': 'Estado bruto do editor visual (opcional).',
3605
+ 'praxis.manualForm.editor.rules.stateTooltip': 'Estado interno somente leitura para round-trip do editor visual; edite formRules.',
3606
+ 'praxis.manualForm.editor.rules.formRulesStateReadonlyHint': 'Gerado pelo editor visual para round-trip; edite formRules.',
3591
3607
  'praxis.manualForm.editor.cascade.title': 'Dependências entre campos',
3592
3608
  'praxis.manualForm.editor.cascade.help': 'Configure cascatas nativas baseadas em metadados.',
3593
3609
  'praxis.manualForm.editor.cascade.note': 'As alterações atualizam metadados e são salvas no rascunho (draft).',
@@ -3687,7 +3703,7 @@ class ManualFormConfigEditorComponent {
3687
3703
  return this.tx('editor.hooks.tooltip', `JSON array of hooks for ${stage} (id, priority, timeoutMs, args).`).replace('{{stage}}', stage);
3688
3704
  }
3689
3705
  formRulesPlaceholder() {
3690
- return this.tx('editor.rules.formRulesPlaceholder', '[{"id":"rule-1","name":"Required rule","targetType":"field","targets":["field"],"effect":{"condition":"{field} != null","properties":{"required":true}}}]');
3706
+ return this.tx('editor.rules.formRulesPlaceholder', '[{"id":"rule-1","name":"Required rule","targetType":"field","targets":["field"],"effect":{"condition":{"!==":[{"var":"field"},null]},"properties":{"required":true}}}]');
3691
3707
  }
3692
3708
  ngOnInit() {
3693
3709
  this.refresh();
@@ -4755,9 +4771,12 @@ class ManualFormConfigEditorComponent {
4755
4771
  matInput
4756
4772
  rows="6"
4757
4773
  [value]="formRulesStateText"
4774
+ readonly
4775
+ aria-readonly="true"
4758
4776
  (input)="onRulesStateTextChange($any($event.target).value)"
4759
4777
  placeholder='{"nodes":[],"edges":[]}'
4760
4778
  ></textarea>
4779
+ <mat-hint>{{ tx('editor.rules.formRulesStateReadonlyHint', 'Generated by the visual editor for round-trip; edit formRules instead.') }}</mat-hint>
4761
4780
  <button
4762
4781
  mat-icon-button
4763
4782
  matSuffix
@@ -4800,7 +4819,7 @@ class ManualFormConfigEditorComponent {
4800
4819
  </mat-tab>
4801
4820
  </mat-tab-group>
4802
4821
  </div>
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"] }] });
4822
+ `, 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.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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"] }] });
4804
4823
  }
4805
4824
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ManualFormConfigEditorComponent, decorators: [{
4806
4825
  type: Component,
@@ -5549,9 +5568,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
5549
5568
  matInput
5550
5569
  rows="6"
5551
5570
  [value]="formRulesStateText"
5571
+ readonly
5572
+ aria-readonly="true"
5552
5573
  (input)="onRulesStateTextChange($any($event.target).value)"
5553
5574
  placeholder='{"nodes":[],"edges":[]}'
5554
5575
  ></textarea>
5576
+ <mat-hint>{{ tx('editor.rules.formRulesStateReadonlyHint', 'Generated by the visual editor for round-trip; edit formRules instead.') }}</mat-hint>
5555
5577
  <button
5556
5578
  mat-icon-button
5557
5579
  matSuffix
@@ -6412,6 +6434,28 @@ const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST = {
6412
6434
  ],
6413
6435
  };
6414
6436
 
6437
+ /** Metadata for Praxis Manual Form component */
6438
+ const PRAXIS_MANUAL_FORM_COMPONENT_METADATA = {
6439
+ id: 'praxis-manual-form',
6440
+ selector: 'praxis-manual-form',
6441
+ component: ManualFormComponent,
6442
+ friendlyName: 'Praxis Manual Form',
6443
+ description: 'Form builder with manual field selection and layout controls.',
6444
+ tags: ['widget', 'form', 'configurable'],
6445
+ lib: '@praxisui/manual-form',
6446
+ };
6447
+ /** Provider para auto-registrar metadados do componente Manual Form. */
6448
+ function providePraxisManualFormMetadata() {
6449
+ return {
6450
+ provide: ENVIRONMENT_INITIALIZER,
6451
+ multi: true,
6452
+ useFactory: (registry) => () => {
6453
+ registry.register(PRAXIS_MANUAL_FORM_COMPONENT_METADATA);
6454
+ },
6455
+ deps: [ComponentMetadataRegistry],
6456
+ };
6457
+ }
6458
+
6415
6459
  /*
6416
6460
  * Public API Surface of praxis-manual-form
6417
6461
  */
@@ -6420,4 +6464,4 @@ const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST = {
6420
6464
  * Generated bundle index. Do not edit.
6421
6465
  */
6422
6466
 
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 };
6467
+ 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, PRAXIS_MANUAL_FORM_COMPONENT_METADATA, createManualFormSeed, providePraxisManualFormMetadata, toFieldMetadataMap };
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@praxisui/manual-form",
3
- "version": "9.0.0-beta.7",
3
+ "version": "9.0.0-beta.71",
4
4
  "description": "Manual form toolkit for Praxis UI: container, instance factory and editor bridge for @praxisui/* fields.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
- "@praxisui/core": "^9.0.0-beta.7",
9
- "@praxisui/dynamic-fields": "^9.0.0-beta.7",
10
- "@praxisui/settings-panel": "^9.0.0-beta.7",
11
- "@praxisui/metadata-editor": "^9.0.0-beta.7",
8
+ "@praxisui/core": "^9.0.0-beta.71",
9
+ "@praxisui/dynamic-fields": "^9.0.0-beta.71",
10
+ "@praxisui/settings-panel": "^9.0.0-beta.71",
11
+ "@praxisui/metadata-editor": "^9.0.0-beta.71",
12
12
  "@angular/cdk": "^21.0.0",
13
13
  "@angular/forms": "^21.0.0",
14
14
  "@angular/material": "^21.0.0",
15
15
  "@angular/router": "^21.0.0",
16
- "@praxisui/ai": "^9.0.0-beta.7",
16
+ "@praxisui/ai": "^9.0.0-beta.71",
17
17
  "rxjs": "~7.8.0"
18
18
  },
19
19
  "dependencies": {
@@ -27,6 +27,7 @@
27
27
  "keywords": [
28
28
  "angular",
29
29
  "praxisui",
30
+ "praxis",
30
31
  "manual-form",
31
32
  "forms",
32
33
  "autosave",
@@ -42,7 +43,10 @@
42
43
  ".": {
43
44
  "types": "./types/praxisui-manual-form.d.ts",
44
45
  "default": "./fesm2022/praxisui-manual-form.mjs"
46
+ },
47
+ "./ai/component-registry.json": {
48
+ "default": "./ai/component-registry.json"
45
49
  }
46
50
  },
47
51
  "type": "module"
48
- }
52
+ }
@@ -1,8 +1,8 @@
1
- import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest } from '@praxisui/core';
1
+ import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiCapabilityCatalog, AiValueKind, ComponentAuthoringManifest, ComponentDocMeta } from '@praxisui/core';
2
2
  import { FormGroup, FormControlName, FormGroupName, AbstractControl, FormControl } from '@angular/forms';
3
3
  import { Observable, BehaviorSubject } from 'rxjs';
4
4
  import * as _angular_core from '@angular/core';
5
- import { AfterContentInit, OnDestroy, OnInit, OnChanges, TemplateRef, ViewContainerRef, SimpleChanges, InjectionToken } from '@angular/core';
5
+ import { AfterContentInit, OnDestroy, OnInit, OnChanges, TemplateRef, ViewContainerRef, SimpleChanges, InjectionToken, Provider } from '@angular/core';
6
6
  import { BaseAiAdapter, PatchResult, PraxisAssistantTurnViewState, PraxisAssistantShellLayout, PraxisAssistantShellLabels, PraxisAssistantSessionSnapshot, PraxisAssistantShellQuickReply, PraxisAssistantShellMessage } from '@praxisui/ai';
7
7
  import { SettingsPanelRef } from '@praxisui/settings-panel';
8
8
 
@@ -568,5 +568,10 @@ declare const MANUAL_FORM_AI_CAPABILITIES: CapabilityCatalog;
568
568
 
569
569
  declare const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST: ComponentAuthoringManifest;
570
570
 
571
- 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 };
571
+ /** Metadata for Praxis Manual Form component */
572
+ declare const PRAXIS_MANUAL_FORM_COMPONENT_METADATA: ComponentDocMeta;
573
+ /** Provider para auto-registrar metadados do componente Manual Form. */
574
+ declare function providePraxisManualFormMetadata(): Provider;
575
+
576
+ 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, PRAXIS_MANUAL_FORM_COMPONENT_METADATA, createManualFormSeed, providePraxisManualFormMetadata, toFieldMetadataMap };
572
577
  export type { Capability, CapabilityCatalog, CapabilityCategory, ManualFieldKeyResolution, ManualFieldMetadataMap, ManualFormDocExampleLevel, ManualFormDocExampleTab, ManualFormId, ManualFormPersistenceOptions, ManualFormSeed, ManualFormSeedOptions, ManualFormSnapshot, ManualFormState, ValueKind };