@praxisui/dynamic-form 9.0.0-beta.42 → 9.0.0-beta.43

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 CHANGED
@@ -140,6 +140,12 @@ fieldsets can render multiple read-only fields per row. Fields without an explic
140
140
  full-width to preserve existing layouts. Generated compact sections also receive semantic header
141
141
  icons derived from their group role, while field icons continue to come from existing schema
142
142
  metadata.
143
+ In runtime rendering, compact detail containers are kept visible only when at least one referenced
144
+ field can actually be materialized after metadata visibility, `visible=false`, `hidden=true` and
145
+ field-rule overrides are applied. Boolean detail fields are valid presentation content, including
146
+ `false` values; marker/flag groups should render their boolean values, not collapse them as empty
147
+ strings. If a section has no materialized fields, the runtime hides the section instead of leaving
148
+ an orphan title.
143
149
  When a migrated detail surface needs the summary density to win over generic schema widths, set
144
150
  `detailSummary.widthPrecedence: "summary"` together with `columns` or `responsiveColumns`. The
145
151
  default is `"schema"`, so existing forms keep honoring `x-ui.width` unless the summary policy
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-07-07T12:05:35.013Z",
3
+ "generatedAt": "2026-07-07T19:18:40.145Z",
4
4
  "packageName": "@praxisui/dynamic-form",
5
- "packageVersion": "9.0.0-beta.42",
5
+ "packageVersion": "9.0.0-beta.43",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 2,
@@ -14009,9 +14009,9 @@ class PraxisDynamicForm {
14009
14009
  const byName = new Map(fieldMetadata.map((f) => [f.name, f]));
14010
14010
  const ordered = [];
14011
14011
  for (const name of fieldNames) {
14012
- if (this.fieldVisibility[name] === false)
14013
- continue;
14014
14012
  const meta = byName.get(name);
14013
+ if (!this.isFieldRenderableInLayout(name, meta))
14014
+ continue;
14015
14015
  if (meta) {
14016
14016
  const overrides = this.fieldRuleProps[name] || {};
14017
14017
  if (Object.keys(overrides).length > 0) {
@@ -14034,6 +14034,18 @@ class PraxisDynamicForm {
14034
14034
  this.columnFieldsCache.set(key, { signature, value: ordered });
14035
14035
  return ordered;
14036
14036
  }
14037
+ isFieldRenderableInLayout(fieldName, field) {
14038
+ const meta = field ??
14039
+ this.getRuntimeFieldMetadata().find((candidate) => candidate.name === fieldName) ??
14040
+ null;
14041
+ if (!meta) {
14042
+ return false;
14043
+ }
14044
+ if (this.fieldVisibility[fieldName] !== undefined) {
14045
+ return this.fieldVisibility[fieldName] === true;
14046
+ }
14047
+ return this.resolveFieldVisibility(meta, this.fieldRuleProps[fieldName] || null);
14048
+ }
14037
14049
  getRichContentLayoutItemDocument(item) {
14038
14050
  return item.kind === 'richContent' && item.document?.kind === 'praxis.rich-content'
14039
14051
  ? item.document
@@ -14053,9 +14065,14 @@ class PraxisDynamicForm {
14053
14065
  return this.resolveRuleVisibility(this.getVisualBlockRuleProps(item.id), true);
14054
14066
  }
14055
14067
  getColumnFieldsSignature(column) {
14068
+ const fieldMetadata = this.getRuntimeFieldMetadata();
14069
+ const byName = new Map(fieldMetadata.map((field) => [field.name, field]));
14056
14070
  return getFormColumnFieldNames(column)
14057
14071
  .map((name) => {
14058
- const visible = this.fieldVisibility[name] === false ? '0' : '1';
14072
+ const meta = byName.get(name);
14073
+ const visible = this.fieldVisibility[name] !== undefined
14074
+ ? this.fieldVisibility[name] === false ? '0' : '1'
14075
+ : this.resolveFieldVisibility(meta ?? null, this.fieldRuleProps[name] || null) ? '1' : '0';
14059
14076
  const overrides = this.fieldRuleProps[name];
14060
14077
  const overrideState = overrides && Object.keys(overrides).length > 0 ? '1' : '0';
14061
14078
  return `${name}:${visible}:${overrideState}`;
@@ -14277,8 +14294,10 @@ class PraxisDynamicForm {
14277
14294
  if (items.some((item) => item.kind === 'richContent' && this.isRichContentLayoutItemVisible(item))) {
14278
14295
  return true;
14279
14296
  }
14280
- // A column is visible if at least one of its fields is visible.
14281
- return getFormLayoutFieldNames(items).some((fieldName) => this.fieldVisibility[fieldName]);
14297
+ // Explicit runtime visibility wins; otherwise resolve metadata/rule visibility directly.
14298
+ return getFormLayoutFieldNames(items).some((fieldName) => {
14299
+ return this.isFieldRenderableInLayout(fieldName);
14300
+ });
14282
14301
  }
14283
14302
  isResponsiveHiddenActive(hidden) {
14284
14303
  if (!hidden || typeof hidden !== 'object' || Array.isArray(hidden)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/dynamic-form",
3
- "version": "9.0.0-beta.42",
3
+ "version": "9.0.0-beta.43",
4
4
  "description": "Angular dynamic form engine for Praxis UI: metadata-driven forms, hooks, and services integrating @praxisui/* packages.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -9,13 +9,13 @@
9
9
  "@angular/forms": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
11
  "@angular/router": "^21.0.0",
12
- "@praxisui/ai": "^9.0.0-beta.42",
13
- "@praxisui/dynamic-fields": "^9.0.0-beta.42",
14
- "@praxisui/metadata-editor": "^9.0.0-beta.42",
15
- "@praxisui/rich-content": "^9.0.0-beta.42",
16
- "@praxisui/settings-panel": "^9.0.0-beta.42",
17
- "@praxisui/visual-builder": "^9.0.0-beta.42",
18
- "@praxisui/core": "^9.0.0-beta.42",
12
+ "@praxisui/ai": "^9.0.0-beta.43",
13
+ "@praxisui/dynamic-fields": "^9.0.0-beta.43",
14
+ "@praxisui/metadata-editor": "^9.0.0-beta.43",
15
+ "@praxisui/rich-content": "^9.0.0-beta.43",
16
+ "@praxisui/settings-panel": "^9.0.0-beta.43",
17
+ "@praxisui/visual-builder": "^9.0.0-beta.43",
18
+ "@praxisui/core": "^9.0.0-beta.43",
19
19
  "rxjs": "^7.8.0"
20
20
  },
21
21
  "dependencies": {
@@ -594,6 +594,12 @@ No ecossistema Praxis, ele funciona tanto como runtime final quanto como superfi
594
594
  | `fieldIconPolicy` | `'all' \| 'presentation-only' \| 'none'` | `'all'` | Active | Controla icones `prefixIcon`/`suffixIcon` vindos da metadata dos campos. `all` preserva o comportamento atual; `presentation-only` mantem icones decorativos no modo apresentacao e oculta os slots de icone em controles input/read-only tradicionais; `none` oculta esses slots em todos os modos. |
595
595
  | `visibleGlobal` | `boolean \| null` | `null` | Active | Visibilidade global propagada para loader. |
596
596
 
597
+ In `compactPresentation` runtime detail surfaces, rows, columns and sections are visible only when
598
+ they contain at least one field that can be materialized after metadata visibility and field-rule
599
+ overrides are resolved. Boolean values, including `false`, are valid presentation values and must
600
+ not be treated as empty detail content. If no field in a section is materialized, the section is
601
+ hidden instead of rendering an orphan title.
602
+
597
603
  #### Migration baseline for ErgonX-style screens
598
604
 
599
605
  For enterprise migrations that must become templates for many screens, `layoutPolicy`,
@@ -1149,6 +1149,7 @@ declare class PraxisDynamicForm implements OnInit, OnChanges, OnDestroy {
1149
1149
  items?: FormLayoutItem[];
1150
1150
  id?: string;
1151
1151
  }): FieldMetadata[];
1152
+ private isFieldRenderableInLayout;
1152
1153
  getRichContentLayoutItemDocument(item: FormLayoutItem): RichContentDocument | null;
1153
1154
  getRichContentLayoutItemLayout(item: FormLayoutItem): 'block' | 'inline';
1154
1155
  private getVisualBlockRuleProps;