@praxisui/crud 9.0.0-beta.3 → 9.0.0-beta.30

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.
@@ -248,6 +248,9 @@ class CrudLauncherService {
248
248
  if (resolved.apiUrlEntry != null) {
249
249
  inputs['apiUrlEntry'] = resolved.apiUrlEntry;
250
250
  }
251
+ if (resolved.layoutPolicy != null) {
252
+ inputs['layoutPolicy'] = resolved.layoutPolicy;
253
+ }
251
254
  if (action.form?.initialValue != null) {
252
255
  inputs['initialValue'] = action.form.initialValue;
253
256
  }
@@ -274,12 +277,14 @@ class CrudLauncherService {
274
277
  submitMethod: action.form?.submitMethod ?? null,
275
278
  apiEndpointKey: action.form?.apiEndpointKey ?? null,
276
279
  apiUrlEntry: action.form?.apiUrlEntry ?? null,
280
+ layoutPolicy: action.form?.layoutPolicy ?? null,
277
281
  };
278
282
  }
279
283
  if (!this.isCanonicalCrudAction(action.action)) {
280
284
  return {
281
285
  apiEndpointKey: action.form?.apiEndpointKey ?? null,
282
286
  apiUrlEntry: action.form?.apiUrlEntry ?? null,
287
+ layoutPolicy: action.form?.layoutPolicy ?? null,
283
288
  };
284
289
  }
285
290
  const resourcePath = String(metadata.resource?.path ?? metadata.table?.resourcePath ?? '').trim();
@@ -309,6 +314,7 @@ class CrudLauncherService {
309
314
  submitMethod: resolved?.submitMethod ?? null,
310
315
  apiEndpointKey: action.form?.apiEndpointKey ?? metadata.resource?.endpointKey ?? null,
311
316
  apiUrlEntry: action.form?.apiUrlEntry ?? null,
317
+ layoutPolicy: action.form?.layoutPolicy ?? null,
312
318
  };
313
319
  }
314
320
  resolveRuntimeContract(action, row, metadata, runtime) {
@@ -4657,7 +4663,7 @@ class PraxisCrudComponent {
4657
4663
  />
4658
4664
  }
4659
4665
  }
4660
- `, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }] });
4666
+ `, isInline: true, styles: [":host{display:block;width:100%;min-width:0;max-width:100%}\n"], dependencies: [{ kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }] });
4661
4667
  }
4662
4668
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisCrudComponent, decorators: [{
4663
4669
  type: Component,
@@ -4756,6 +4762,7 @@ class DynamicFormDialogHostComponent {
4756
4762
  submitMethod;
4757
4763
  apiEndpointKey;
4758
4764
  apiUrlEntry;
4765
+ layoutPolicy;
4759
4766
  formActions;
4760
4767
  mode = 'create';
4761
4768
  backConfig;
@@ -4812,6 +4819,7 @@ class DynamicFormDialogHostComponent {
4812
4819
  this.apiUrlEntry = this.data.inputs?.['apiUrlEntry'] ?? null;
4813
4820
  const act = this.data.action?.action;
4814
4821
  this.mode = act === 'edit' ? 'edit' : act === 'view' ? 'view' : 'create';
4822
+ this.layoutPolicy = this.resolveLayoutPolicy();
4815
4823
  this.formActions = this.resolveFormActions();
4816
4824
  // Back config: defaults from metadata/action, overridden by saved per-form config
4817
4825
  const defaults = (this.data.action?.back || this.data.metadata?.defaults?.back) || {};
@@ -4857,6 +4865,7 @@ class DynamicFormDialogHostComponent {
4857
4865
  'apiEndpointKey',
4858
4866
  'apiUrlEntry',
4859
4867
  'initialValue',
4868
+ 'layoutPolicy',
4860
4869
  ]);
4861
4870
  const explicit = inputs['initialValue'] && typeof inputs['initialValue'] === 'object'
4862
4871
  ? { ...inputs['initialValue'] }
@@ -4890,6 +4899,15 @@ class DynamicFormDialogHostComponent {
4890
4899
  },
4891
4900
  };
4892
4901
  }
4902
+ resolveLayoutPolicy() {
4903
+ const explicit = this.data.inputs?.['layoutPolicy'] ??
4904
+ this.data.action?.form?.layoutPolicy ??
4905
+ this.data.action?.layoutPolicy;
4906
+ if (explicit && typeof explicit === 'object') {
4907
+ return explicit;
4908
+ }
4909
+ return null;
4910
+ }
4893
4911
  resolveSubmitLabel() {
4894
4912
  const action = this.data.action ?? {};
4895
4913
  const explicit = stringOrUndefined(action.form?.submitLabel ??
@@ -5074,6 +5092,7 @@ class DynamicFormDialogHostComponent {
5074
5092
  [submitMethod]="submitMethod"
5075
5093
  [apiEndpointKey]="apiEndpointKey"
5076
5094
  [apiUrlEntry]="apiUrlEntry"
5095
+ [layoutPolicy]="layoutPolicy"
5077
5096
  [presentationModeGlobal]="mode === 'view' ? true : null"
5078
5097
  [backConfig]="backConfig"
5079
5098
  [actions]="formActions"
@@ -5081,7 +5100,7 @@ class DynamicFormDialogHostComponent {
5081
5100
  (formCancel)="onCancel()"
5082
5101
  ></praxis-dynamic-form>
5083
5102
  </mat-dialog-content>
5084
- `, isInline: true, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);padding:0 var(--dlg-pad);height:var(--dlg-header-h);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}.dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange"] }] });
5103
+ `, isInline: true, styles: [":host{--dlg-header-h: 56px;--dlg-footer-h: 56px;--dlg-pad: 16px;display:flex;flex-direction:column;height:100%;overflow:hidden}:host([data-density=\"compact\"]){--dlg-header-h: 44px;--dlg-footer-h: 44px;--dlg-pad: 12px}.dialog-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:var(--dlg-pad);padding:0 var(--dlg-pad);height:var(--dlg-header-h);margin:0;background:var(--md-sys-color-surface-container-high);border-bottom:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface)}.dialog-title{margin:0;font:inherit;font-weight:600;color:var(--md-sys-color-on-surface)}.spacer{flex:1}.dialog-content{overflow:auto;padding:var(--dlg-pad);max-height:calc(100svh - var(--dlg-header-h) - 32px)}.dialog-header button.mat-icon-button{color:var(--md-sys-color-on-surface-variant)}.dialog-header button.mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}.dialog-footer{position:sticky;bottom:0;z-index:1;padding:var(--dlg-pad)}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "initialValue", "editorialContext", "mode", "config", "actions", "schemaSource", "schemaUrl", "readUrl", "submitUrl", "submitMethod", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "showAiAssistant", "formId", "componentInstanceId", "configPersistenceStrategy", "layout", "generatedLayoutPreset", "layoutPolicy", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "fieldIconPolicy", "domainRules", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "configPatchChange", "formReady", "valueChange", "syncCompleted", "initializationError", "loadingStateChange", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError", "ruleDiagnosticsChange"] }] });
5085
5104
  }
5086
5105
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicFormDialogHostComponent, decorators: [{
5087
5106
  type: Component,
@@ -5136,6 +5155,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
5136
5155
  [submitMethod]="submitMethod"
5137
5156
  [apiEndpointKey]="apiEndpointKey"
5138
5157
  [apiUrlEntry]="apiUrlEntry"
5158
+ [layoutPolicy]="layoutPolicy"
5139
5159
  [presentationModeGlobal]="mode === 'view' ? true : null"
5140
5160
  [backConfig]="backConfig"
5141
5161
  [actions]="formActions"
@@ -5699,6 +5719,7 @@ const CRUD_AI_CAPABILITIES = {
5699
5719
  { path: 'actions[].params[].to', category: 'actions', valueKind: 'enum', allowedValues: ENUMS.paramTarget, description: 'Destino do parametro.' },
5700
5720
  { path: 'actions[].params[].name', category: 'actions', valueKind: 'string', description: 'Nome do parametro no destino.' },
5701
5721
  { path: 'actions[].form.initialValue', category: 'actions', valueKind: 'object', description: 'Seed fixo do formulario injetado em inputs.initialValue antes da abertura.' },
5722
+ { path: 'actions[].form.layoutPolicy', category: 'actions', valueKind: 'object', description: 'Politica schema-driven opt-in encaminhada ao Dynamic Form para materializar detalhe ou command form sem FormConfig.sections local; deve acompanhar schemaUrl compativel, especialmente schemaType=request para comandos.' },
5702
5723
  { path: 'actions[].back', category: 'navigation', valueKind: 'object', description: 'BackConfig por acao.' },
5703
5724
  { path: 'actions[].back.strategy', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.backStrategy, description: 'Estrategia de retorno da acao (auto, close, navigate).' },
5704
5725
  { path: 'actions[].back.returnTo', category: 'navigation', valueKind: 'string', description: 'Rota ou destino usado quando a estrategia de retorno for navigate.' },
@@ -5736,6 +5757,7 @@ const surfaceConfigureSchema = {
5736
5757
  submitMethod: { enum: ['post', 'put', 'patch', 'delete'] },
5737
5758
  apiEndpointKey: { type: 'string' },
5738
5759
  initialValue: { type: 'object' },
5760
+ layoutPolicy: { type: 'object' },
5739
5761
  },
5740
5762
  },
5741
5763
  params: {
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@praxisui/crud",
3
- "version": "9.0.0-beta.3",
3
+ "version": "9.0.0-beta.30",
4
4
  "description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
- "@praxisui/dynamic-form": "^9.0.0-beta.3",
9
- "@praxisui/table": "^9.0.0-beta.3",
10
- "@praxisui/core": "^9.0.0-beta.3",
11
- "@praxisui/dynamic-fields": "^9.0.0-beta.3",
12
- "@praxisui/settings-panel": "^9.0.0-beta.3",
8
+ "@praxisui/dynamic-form": "^9.0.0-beta.30",
9
+ "@praxisui/table": "^9.0.0-beta.30",
10
+ "@praxisui/core": "^9.0.0-beta.30",
11
+ "@praxisui/dynamic-fields": "^9.0.0-beta.30",
12
+ "@praxisui/settings-panel": "^9.0.0-beta.30",
13
13
  "@angular/cdk": "^21.0.0",
14
14
  "@angular/forms": "^21.0.0",
15
15
  "@angular/material": "^21.0.0",
16
16
  "@angular/router": "^21.0.0",
17
- "@praxisui/ai": "^9.0.0-beta.3",
17
+ "@praxisui/ai": "^9.0.0-beta.30",
18
18
  "rxjs": "~7.8.0"
19
19
  },
20
20
  "dependencies": {
@@ -28,6 +28,7 @@
28
28
  "keywords": [
29
29
  "angular",
30
30
  "praxisui",
31
+ "praxis",
31
32
  "crud",
32
33
  "admin",
33
34
  "backoffice",
@@ -48,7 +49,10 @@
48
49
  "./drawer-adapter": {
49
50
  "types": "./types/praxisui-crud-drawer-adapter.d.ts",
50
51
  "default": "./fesm2022/praxisui-crud-drawer-adapter.mjs"
52
+ },
53
+ "./ai/component-registry.json": {
54
+ "default": "./ai/component-registry.json"
51
55
  }
52
56
  },
53
57
  "type": "module"
54
- }
58
+ }
@@ -1,5 +1,5 @@
1
1
  import * as _praxisui_core from '@praxisui/core';
2
- import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
2
+ import { RowAction, ToolbarAction, ApiEndpoint, ApiUrlEntry, DynamicFormLayoutPolicy, BackConfig, TableConfig, PraxisDataQueryContext, FormConfig, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, LoadingState, RestApiLinks, ResourceCapabilitySnapshot, GenericCrudService, AsyncConfigStorage, ComponentDocMeta, AiCapabilityCatalog, AiCapability, AiCapabilityCategory, AiValueKind, ComponentAuthoringManifest, SettingsValueProvider } from '@praxisui/core';
3
3
  export { BackConfig } from '@praxisui/core';
4
4
  import * as _angular_core from '@angular/core';
5
5
  import { NgZone, OnChanges, EventEmitter, SimpleChanges, OnInit, Provider, AfterViewInit, OnDestroy } from '@angular/core';
@@ -53,6 +53,7 @@ interface CrudActionFormContract {
53
53
  apiEndpointKey?: ApiEndpoint | string | null;
54
54
  apiUrlEntry?: ApiUrlEntry | null;
55
55
  initialValue?: Record<string, unknown> | null;
56
+ layoutPolicy?: DynamicFormLayoutPolicy | null;
56
57
  }
57
58
  type CrudActionResolutionMode = 'inferred' | 'explicit';
58
59
  type CrudAction = (RowAction | ToolbarAction) & {
@@ -316,6 +317,7 @@ declare class CrudLauncherService {
316
317
  submitMethod?: string | null;
317
318
  apiEndpointKey?: unknown;
318
319
  apiUrlEntry?: unknown;
320
+ layoutPolicy?: unknown;
319
321
  };
320
322
  private buildInferredFormId;
321
323
  private isCanonicalCrudAction;
@@ -347,6 +349,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
347
349
  submitMethod?: string | null;
348
350
  apiEndpointKey?: ApiEndpoint | string | null;
349
351
  apiUrlEntry?: ApiUrlEntry | null;
352
+ layoutPolicy?: DynamicFormLayoutPolicy | null;
350
353
  formActions?: FormConfig['actions'];
351
354
  mode: 'create' | 'edit' | 'view';
352
355
  backConfig?: BackConfig;
@@ -355,6 +358,7 @@ declare class DynamicFormDialogHostComponent implements OnInit {
355
358
  constructor(dialogRef: DialogRef<DynamicFormDialogHostComponent>, data: any, dialogService: DialogService, crud: GenericCrudService<any>, configStorage: AsyncConfigStorage);
356
359
  private extractInitialValue;
357
360
  private resolveFormActions;
361
+ private resolveLayoutPolicy;
358
362
  private resolveSubmitLabel;
359
363
  ngOnInit(): void;
360
364
  onSave(result: unknown): void;