ng-form-foundry 0.5.3 → 0.5.5

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/index.d.ts CHANGED
@@ -327,6 +327,24 @@ declare function addMapEntry(group: FormGroup, map: NodeMap, key?: string): stri
327
327
  declare function renameMapEntry(group: FormGroup, map: NodeMap, oldKey: string, newKey: string): boolean;
328
328
  /** Remove entry `key` unless the map is at `minEntries`. Returns whether it was removed. */
329
329
  declare function removeMapEntry(group: FormGroup, map: NodeMap, key: string): boolean;
330
+ /**
331
+ * Materialize or de-materialize an optional (presence) child of `group`,
332
+ * mirroring the presence toggle the form UI offers — but callable by any host
333
+ * holding the {@link FormGroup}, for a key at any depth. `present: true` builds
334
+ * the child fresh from `schema` (seeded with `initial` if given; nested
335
+ * presence descendants start absent, as {@link buildControl}); `present: false`
336
+ * removes it, dropping the key from the form value.
337
+ *
338
+ * The materialize direction is why the coupling exists: a materialized
339
+ * non-nullable presence leaf carries `Validators.required`, because an
340
+ * enabled-but-empty key would serialize as `null` and fail a typed schema. A
341
+ * host that materializes fields for editing therefore drops the ones left
342
+ * empty on cancel by de-materializing them — this API is that primitive.
343
+ *
344
+ * `schema` must be the presence node for `key`; a non-presence `schema` is a
345
+ * no-op. Returns whether the form changed.
346
+ */
347
+ declare function setNodePresence(group: FormGroup, schema: NodeType, key: string, present: boolean, initial?: unknown): boolean;
330
348
  /**
331
349
  * Build the `AbstractControl` for a single schema node.
332
350
  *
@@ -525,7 +543,8 @@ declare class DynamicRecursiveFormComponent implements OnInit {
525
543
  * Add or remove a presence node's control on this form — any presence kind:
526
544
  * group, leaf, map, or choice. Removing it drops the key from `form.value`;
527
545
  * adding it builds the control fresh from its schema (nested presence
528
- * children start absent).
546
+ * children start absent). Delegates to {@link setNodePresence}, the
547
+ * host-callable primitive.
529
548
  */
530
549
  toggleNodePresence(key: string, schema: NodeType, present: boolean): void;
531
550
  /**
@@ -638,6 +657,7 @@ interface TreeNode {
638
657
  /** Present on a present optional child node: drives the row's remove control. */
639
658
  presenceRemovable?: {
640
659
  key: string;
660
+ schema: NodeType;
641
661
  };
642
662
  /** Field-layout appearance inherited from ancestor groups, for the node's detail-section form. */
643
663
  inherited?: Appearance | null;
@@ -698,6 +718,22 @@ declare class ConfigEditorComponent implements OnDestroy {
698
718
  * shows on the next rebind or structural rebuild, not immediately.
699
719
  */
700
720
  readonly rootTitle: _angular_core.InputSignal<string | undefined>;
721
+ /**
722
+ * Whether selecting a tree row also expands the node's own children.
723
+ * Off by default: a click selects (the detail pane shows the subtree
724
+ * anyway) and the twisty alone controls expansion, so browsing a deep
725
+ * config does not keep unfolding the tree. Ancestors of the selection are
726
+ * always expanded — the selected row itself must stay visible.
727
+ */
728
+ readonly expandOnClick: _angular_core.InputSignal<boolean>;
729
+ /**
730
+ * Whether the detail pane shows its top breadcrumb (the selected node's
731
+ * path, with the member remove control beside it). Hosts whose tree
732
+ * already tells the user where they are can turn it off — the section
733
+ * trail headings inside the detail stay, and member removal remains
734
+ * available on the tree rows and section headings.
735
+ */
736
+ readonly showBreadcrumb: _angular_core.InputSignal<boolean>;
701
737
  root: TreeNode;
702
738
  selected: TreeNode | null;
703
739
  /** The selected subtree as a flat, breadcrumb-separated section list. */
@@ -708,6 +744,7 @@ declare class ConfigEditorComponent implements OnDestroy {
708
744
  private shape;
709
745
  private changes?;
710
746
  private readonly host;
747
+ private readonly cdr;
711
748
  /** Stable per-instance ids for the shape signature, so replacing a control (setControl) reads as a structural change. */
712
749
  private readonly controlIds;
713
750
  private controlIdSeq;
@@ -715,6 +752,15 @@ declare class ConfigEditorComponent implements OnDestroy {
715
752
  ngOnDestroy(): void;
716
753
  /** Bind the editor to a schema/form pair: fresh tree, root selection, and shape-sync subscription. */
717
754
  private attach;
755
+ /**
756
+ * Force the editor to re-read the bound form. Call this when the form was
757
+ * mutated in a way the editor's own `valueChanges` subscription could not
758
+ * observe — a structural change made with `{ emitEvent: false }`, or a
759
+ * mutation while a detached change detector left the view unchecked. It
760
+ * re-syncs the tree structure, rebuilds the current selection's sections
761
+ * from the live controls, and renders them.
762
+ */
763
+ refresh(): void;
718
764
  select(node: TreeNode, reveal?: boolean): void;
719
765
  /**
720
766
  * Root-to-`target` path for the detail-pane breadcrumb (inclusive of both ends),
@@ -889,7 +935,7 @@ declare class ConfigEditorComponent implements OnDestroy {
889
935
  */
890
936
  private escapeSeg;
891
937
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConfigEditorComponent, never>;
892
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfigEditorComponent, "nff-config-editor", never, { "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "formGroup": { "alias": "formGroup"; "required": true; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "rootTitle": { "alias": "rootTitle"; "required": false; "isSignal": true; }; }, { "editable": "editableChange"; }, never, never, true, never>;
938
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfigEditorComponent, "nff-config-editor", never, { "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "formGroup": { "alias": "formGroup"; "required": true; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "rootTitle": { "alias": "rootTitle"; "required": false; "isSignal": true; }; "expandOnClick": { "alias": "expandOnClick"; "required": false; "isSignal": true; }; "showBreadcrumb": { "alias": "showBreadcrumb"; "required": false; "isSignal": true; }; }, { "editable": "editableChange"; }, never, never, true, never>;
893
939
  }
894
940
 
895
941
  declare class LeafRendererComponent implements AfterViewInit {
@@ -924,6 +970,7 @@ declare class LeafListRendererComponent implements OnInit {
924
970
  formArray: any;
925
971
  editable: boolean;
926
972
  minItems: number;
973
+ maxItems: number;
927
974
  /**
928
975
  * The parent group's grid layout (its `fieldsLayout` styles). A stacked list
929
976
  * spans the parent's full row, so its entries repeat the same tracks and
@@ -945,10 +992,14 @@ declare class LeafListRendererComponent implements OnInit {
945
992
  /** Applies {@link layout} to the host (the entries' container) while stacked. */
946
993
  get hostLayout(): LayoutStyles | null;
947
994
  ngOnInit(): void;
995
+ get effectiveMin(): number;
996
+ get effectiveMax(): number;
997
+ /** Whether another item may be appended (below the effective maximum). */
998
+ get canAdd(): boolean;
948
999
  removeItem($index: number): void;
949
1000
  addItem(): void;
950
1001
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LeafListRendererComponent, never>;
951
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LeafListRendererComponent, "nff-leaf-list-renderer", never, { "leaf_": { "alias": "leaf_"; "required": false; }; "initialValue": { "alias": "initialValue"; "required": false; }; "formArray": { "alias": "formArray"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "minItems": { "alias": "minItems"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; }, { "message": "message"; }, never, never, true, never>;
1002
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LeafListRendererComponent, "nff-leaf-list-renderer", never, { "leaf_": { "alias": "leaf_"; "required": false; }; "initialValue": { "alias": "initialValue"; "required": false; }; "formArray": { "alias": "formArray"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "minItems": { "alias": "minItems"; "required": false; }; "maxItems": { "alias": "maxItems"; "required": false; }; "layout": { "alias": "layout"; "required": false; }; }, { "message": "message"; }, never, never, true, never>;
952
1003
  }
953
1004
 
954
1005
  declare class LeafEnumRendererComponent {
@@ -1040,9 +1091,13 @@ declare class NodeGroupListRendererComponent implements OnInit, AfterViewInit {
1040
1091
  items: QueryList<DynamicRecursiveFormComponent>;
1041
1092
  cdr: ChangeDetectorRef;
1042
1093
  ngOnInit(): void;
1094
+ get effectiveMin(): number;
1095
+ get effectiveMax(): number;
1096
+ /** Whether another item may be appended (below the effective maximum). */
1097
+ get canAdd(): boolean;
1043
1098
  ngAfterViewInit(): void;
1044
1099
  removeItem($index: number): void;
1045
- addItem: (index: number) => void;
1100
+ addItem: (index?: number) => void;
1046
1101
  setLastEditable(): void;
1047
1102
  asFormGroup(group: any): FormGroup;
1048
1103
  getTitle($index: number): string;
@@ -1078,6 +1133,10 @@ declare class NodeMapRendererComponent implements OnChanges {
1078
1133
  get valueLeaf(): Leaf;
1079
1134
  /** The value schema as a group (used when `value.kind === 'nodeGroup'`). */
1080
1135
  get valueGroup(): NodeGroup;
1136
+ /** Narrowing casts for the complex value kinds the template renders. */
1137
+ protected asLeafList(v: unknown): LeafList;
1138
+ protected asNodeGroupList(v: unknown): NodeGroupList;
1139
+ protected asNodeMap(v: unknown): NodeMap;
1081
1140
  get atMax(): boolean;
1082
1141
  get atMin(): boolean;
1083
1142
  /** Append a new entry under a unique placeholder key. Delegates to {@link addMapEntry}. */
@@ -1092,9 +1151,10 @@ declare class NodeMapRendererComponent implements OnChanges {
1092
1151
  renameEntry(oldKey: string, rawKey: string): void;
1093
1152
  protected readonly asFormControl: typeof asFormControl;
1094
1153
  protected readonly asFormGroup: typeof asFormGroup;
1154
+ protected readonly asFormArray: typeof asFormArray;
1095
1155
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<NodeMapRendererComponent, never>;
1096
1156
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<NodeMapRendererComponent, "nff-node-map-renderer", never, { "nodeMap": { "alias": "nodeMap"; "required": false; }; "formGroup": { "alias": "formGroup"; "required": false; }; "editable": { "alias": "editable"; "required": false; }; "showAbsentOptionals": { "alias": "showAbsentOptionals"; "required": false; }; "inheritedAppearance": { "alias": "inheritedAppearance"; "required": false; }; }, {}, never, never, true, never>;
1097
1157
  }
1098
1158
 
1099
- export { CASE_KEY, ConfigEditorComponent, DynamicRecursiveFormComponent, LeafEnumRendererComponent, LeafListRendererComponent, LeafRendererComponent, NodeGroupListRendererComponent, NodeMapRendererComponent, RadixInputDirective, addMapEntry, buildControl, buildFormFromSchema, caseDisplayLabels, caseFields, defineSchema, formatRadix, removeMapEntry, renameMapEntry, resolveChoiceCase, serializeForm, switchChoiceCase, toWireValue };
1159
+ export { CASE_KEY, ConfigEditorComponent, DynamicRecursiveFormComponent, LeafEnumRendererComponent, LeafListRendererComponent, LeafRendererComponent, NodeGroupListRendererComponent, NodeMapRendererComponent, RadixInputDirective, addMapEntry, buildControl, buildFormFromSchema, caseDisplayLabels, caseFields, defineSchema, formatRadix, removeMapEntry, renameMapEntry, resolveChoiceCase, serializeForm, setNodePresence, switchChoiceCase, toWireValue };
1100
1160
  export type { AnonLeaf, Appearance, ChoiceCase, DFormControl, DFormGroup, FormGroupType, Leaf, LeafBase, LeafBoolean, LeafEnum, LeafList, LeafNumber, LeafRuntimeType, LeafString, NodeChoice, NodeGroup, NodeGroupList, NodeMap, NodeType, Radix };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-form-foundry",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Build fully-typed Angular Reactive Forms and Angular Material UI from a declarative, recursive form-description schema.",
5
5
  "keywords": [
6
6
  "angular",