@ng-forge/dynamic-form-mcp 1.0.0-rc.3 → 1.0.0

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.
@@ -650,9 +650,9 @@ var FIELD_TYPES = [
650
650
  minimalExample: `{ key: 'submit', type: 'submit', label: 'Submit' }`
651
651
  },
652
652
  {
653
- type: "addArrayItem",
653
+ type: "add-array-item",
654
654
  category: "button",
655
- description: "Button to add a new item to an array field. Must be placed within or near the array container.",
655
+ description: "Button to append a new item to the end of an array field. Must be placed within or near the array container. (Legacy alias: addArrayItem.)",
656
656
  valueType: void 0,
657
657
  baseInterface: "FieldDef",
658
658
  props: {},
@@ -661,15 +661,50 @@ var FIELD_TYPES = [
661
661
  allowedIn: ["array", "row", "group"],
662
662
  example: `{
663
663
  key: 'addContact',
664
- type: 'addArrayItem',
664
+ type: 'add-array-item',
665
665
  label: 'Add Contact'
666
666
  }`,
667
- minimalExample: `{ key: 'add', type: 'addArrayItem', label: 'Add Item' }`
667
+ minimalExample: `{ key: 'add', type: 'add-array-item', label: 'Add Item' }`
668
668
  },
669
669
  {
670
- type: "removeArrayItem",
670
+ type: "prepend-array-item",
671
671
  category: "button",
672
- description: "Button to remove the current item from an array field. Typically placed within each array item template.",
672
+ description: "Button to add a new item to the beginning of an array field. (Legacy alias: prependArrayItem.)",
673
+ valueType: void 0,
674
+ baseInterface: "FieldDef",
675
+ props: {},
676
+ validationSupported: false,
677
+ source: "adapter",
678
+ allowedIn: ["array", "row", "group"],
679
+ example: `{
680
+ key: 'prependContact',
681
+ type: 'prepend-array-item',
682
+ label: 'Add to Top'
683
+ }`,
684
+ minimalExample: `{ key: 'prepend', type: 'prepend-array-item', label: 'Add First' }`
685
+ },
686
+ {
687
+ type: "insert-array-item",
688
+ category: "button",
689
+ description: "Button to insert a new item at a specific index in an array field (set via the index property). (Legacy alias: insertArrayItem.)",
690
+ valueType: void 0,
691
+ baseInterface: "FieldDef",
692
+ props: {},
693
+ validationSupported: false,
694
+ source: "adapter",
695
+ allowedIn: ["array", "row", "group"],
696
+ example: `{
697
+ key: 'insertContact',
698
+ type: 'insert-array-item',
699
+ label: 'Insert',
700
+ index: 1
701
+ }`,
702
+ minimalExample: `{ key: 'insert', type: 'insert-array-item', label: 'Insert', index: 0 }`
703
+ },
704
+ {
705
+ type: "remove-array-item",
706
+ category: "button",
707
+ description: "Button to remove the current item from an array field. Typically placed within each array item template. (Legacy alias: removeArrayItem.)",
673
708
  valueType: void 0,
674
709
  baseInterface: "FieldDef",
675
710
  props: {},
@@ -678,10 +713,46 @@ var FIELD_TYPES = [
678
713
  allowedIn: ["array", "row", "group"],
679
714
  example: `{
680
715
  key: 'removeContact',
681
- type: 'removeArrayItem',
716
+ type: 'remove-array-item',
682
717
  label: 'Remove'
683
718
  }`,
684
- minimalExample: `{ key: 'remove', type: 'removeArrayItem', label: 'Remove' }`
719
+ minimalExample: `{ key: 'remove', type: 'remove-array-item', label: 'Remove' }`
720
+ },
721
+ {
722
+ type: "pop-array-item",
723
+ category: "button",
724
+ description: "Button to remove the last item from an array field. (Legacy alias: popArrayItem.)",
725
+ valueType: void 0,
726
+ baseInterface: "FieldDef",
727
+ props: {},
728
+ validationSupported: false,
729
+ source: "adapter",
730
+ allowedIn: ["array", "row", "group"],
731
+ example: `{
732
+ key: 'popContact',
733
+ type: 'pop-array-item',
734
+ label: 'Remove Last',
735
+ arrayKey: 'contacts'
736
+ }`,
737
+ minimalExample: `{ key: 'pop', type: 'pop-array-item', label: 'Remove Last', arrayKey: 'items' }`
738
+ },
739
+ {
740
+ type: "shift-array-item",
741
+ category: "button",
742
+ description: "Button to remove the first item from an array field. (Legacy alias: shiftArrayItem.)",
743
+ valueType: void 0,
744
+ baseInterface: "FieldDef",
745
+ props: {},
746
+ validationSupported: false,
747
+ source: "adapter",
748
+ allowedIn: ["array", "row", "group"],
749
+ example: `{
750
+ key: 'shiftContact',
751
+ type: 'shift-array-item',
752
+ label: 'Remove First',
753
+ arrayKey: 'contacts'
754
+ }`,
755
+ minimalExample: `{ key: 'shift', type: 'shift-array-item', label: 'Remove First', arrayKey: 'items' }`
685
756
  }
686
757
  ];
687
758
 
@@ -1472,7 +1543,7 @@ var WRAPPERS = [
1472
1543
  category: "demo",
1473
1544
  availability: "demo-only",
1474
1545
  package: "@internal/examples-shared-ui",
1475
- description: 'Demo wrapper used by the docs sandbox. Wraps an array field in a titled card whose header contains an "Add" button \u2014 the wrapper owns the append behaviour, dispatching `arrayEvent(key).append(itemTemplate)` on click via the `EventBus`. Lets the consumer config drop the separate `addArrayItem` button field. NOT a shipping primitive; copy the component out of `internal/examples-shared-ui/src/lib/demo-wrappers/` or author your own if you want this pattern in production.',
1546
+ description: 'Demo wrapper used by the docs sandbox. Wraps an array field in a titled card whose header contains an "Add" button \u2014 the wrapper owns the append behaviour, dispatching `arrayEvent(key).append(itemTemplate)` on click via the `EventBus`. Lets the consumer config drop the separate `add-array-item` button field. NOT a shipping primitive; copy the component out of `internal/examples-shared-ui/src/lib/demo-wrappers/` or author your own if you want this pattern in production.',
1476
1547
  props: {
1477
1548
  title: {
1478
1549
  name: "title",
@@ -2828,6 +2899,8 @@ Evaluates a JavaScript expression with access to \`formValue\`, \`fieldValue\`,
2828
2899
  }
2829
2900
  \`\`\`
2830
2901
 
2902
+ **Condition scoping:** in logic conditions, \`formValue\` is the whole form value regardless of where the field sits, except inside array items where it is scoped to the current item (use \`rootFormValue\` for the rest of the form). Reference group-nested fields by their full path, e.g. \`formValue.person.firstName\`. Note that \`derivation\` expressions scope differently: there \`formValue\` is also scoped to the parent group for group-nested fields.
2903
+
2831
2904
  #### Custom Condition
2832
2905
 
2833
2906
  Invokes a registered custom function by name:
@@ -3005,7 +3078,7 @@ All features are exported from \`@ng-forge/dynamic-forms\`.
3005
3078
 
3006
3079
  ## CRITICAL: UI Library Differences
3007
3080
 
3008
- Different UI libraries support different properties. Always validate against the correct library using \`ngforge_validate_form_config\` with the appropriate \`uiIntegration\` parameter.
3081
+ Different UI libraries support different properties. Always validate against the correct library using \`ngforge_validate\` with the appropriate \`uiIntegration\` parameter.
3009
3082
 
3010
3083
  ### Property Differences by Library
3011
3084
 
@@ -3048,24 +3121,24 @@ Container fields (\`page\`, \`group\`, \`row\`) do NOT support these properties:
3048
3121
  { key: 'volume', type: 'slider', label: 'Volume', min: 0, max: 100 }
3049
3122
  \`\`\`
3050
3123
 
3051
- 5. **Using unsupported field types** - Each UI library supports specific field types. Use \`ngforge_get_field_schema\` to see available types.
3124
+ 5. **Using unsupported field types** - Each UI library supports specific field types. Use \`ngforge_lookup\` with \`depth: "schema"\` to see available types.
3052
3125
 
3053
3126
  ## Validation Before Use
3054
3127
 
3055
- Always validate your FormConfig using the \`ngforge_validate_form_config\` tool before using it. This tool uses the actual TypeScript/Zod schemas, so if validation passes, the config will work correctly at runtime.
3128
+ Always validate your FormConfig using the \`ngforge_validate\` tool before using it. This tool uses the actual TypeScript/Zod schemas, so if validation passes, the config will work correctly at runtime.
3056
3129
 
3057
3130
  \`\`\`typescript
3058
3131
  // Always specify the UI integration you're using
3059
- ngforge_validate_form_config({
3132
+ ngforge_validate({
3060
3133
  uiIntegration: 'material', // or 'bootstrap', 'primeng', 'ionic'
3061
3134
  config: { fields: [...] }
3062
3135
  })
3063
3136
  \`\`\`
3064
3137
 
3065
- To understand what properties are supported for each field type, use \`ngforge_get_field_schema\`:
3138
+ To understand what properties are supported for each field type, use \`ngforge_lookup\` with \`depth: "schema"\`:
3066
3139
 
3067
3140
  \`\`\`typescript
3068
- ngforge_get_field_schema({ uiIntegration: 'material' })
3141
+ ngforge_lookup({ topic: 'input', depth: 'schema', uiIntegration: 'material' })
3069
3142
  \`\`\`
3070
3143
  `;
3071
3144
 
@@ -5178,7 +5251,7 @@ var MatPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5178
5251
  props: MatButtonPropsSchema.optional()
5179
5252
  });
5180
5253
  var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5181
- type: z33.literal("addArrayItem"),
5254
+ type: z33.literal("add-array-item"),
5182
5255
  /**
5183
5256
  * Key of the array field to add items to.
5184
5257
  * If omitted, uses the parent array context.
@@ -5187,7 +5260,7 @@ var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5187
5260
  props: MatButtonPropsSchema.optional()
5188
5261
  });
5189
5262
  var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5190
- type: z33.literal("removeArrayItem"),
5263
+ type: z33.literal("remove-array-item"),
5191
5264
  /**
5192
5265
  * Key of the array field to remove items from.
5193
5266
  * If omitted, uses the parent array context.
@@ -5195,6 +5268,44 @@ var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5195
5268
  arrayKey: z33.string().optional(),
5196
5269
  props: MatButtonPropsSchema.optional()
5197
5270
  });
5271
+ var MatPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5272
+ type: z33.literal("prepend-array-item"),
5273
+ /**
5274
+ * Key of the array field to prepend items to.
5275
+ * If omitted, uses the parent array context.
5276
+ */
5277
+ arrayKey: z33.string().optional(),
5278
+ props: MatButtonPropsSchema.optional()
5279
+ });
5280
+ var MatInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5281
+ type: z33.literal("insert-array-item"),
5282
+ /**
5283
+ * Key of the array field to insert items into.
5284
+ * If omitted, uses the parent array context.
5285
+ */
5286
+ arrayKey: z33.string().optional(),
5287
+ /**
5288
+ * Index at which to insert the new item.
5289
+ */
5290
+ index: z33.number(),
5291
+ props: MatButtonPropsSchema.optional()
5292
+ });
5293
+ var MatPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5294
+ type: z33.literal("pop-array-item"),
5295
+ /**
5296
+ * Key of the array field to pop items from.
5297
+ */
5298
+ arrayKey: z33.string(),
5299
+ props: MatButtonPropsSchema.optional()
5300
+ });
5301
+ var MatShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5302
+ type: z33.literal("shift-array-item"),
5303
+ /**
5304
+ * Key of the array field to shift items from.
5305
+ */
5306
+ arrayKey: z33.string(),
5307
+ props: MatButtonPropsSchema.optional()
5308
+ });
5198
5309
 
5199
5310
  // internal/dynamic-forms-zod/material/src/mat-leaf-field.schema.ts
5200
5311
  import { z as z36 } from "zod";
@@ -5270,7 +5381,11 @@ var MatLeafFieldSchema = z36.discriminatedUnion("type", [
5270
5381
  MatNextButtonFieldSchema,
5271
5382
  MatPreviousButtonFieldSchema,
5272
5383
  MatAddArrayItemButtonFieldSchema,
5273
- MatRemoveArrayItemButtonFieldSchema
5384
+ MatRemoveArrayItemButtonFieldSchema,
5385
+ MatPrependArrayItemButtonFieldSchema,
5386
+ MatInsertArrayItemButtonFieldSchema,
5387
+ MatPopArrayItemButtonFieldSchema,
5388
+ MatShiftArrayItemButtonFieldSchema
5274
5389
  ]).superRefine(nullableValueRefine);
5275
5390
 
5276
5391
  // internal/dynamic-forms-zod/src/lib/schemas/containers/factories.ts
@@ -5738,15 +5853,36 @@ var BsPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5738
5853
  props: BsButtonPropsSchema.optional()
5739
5854
  });
5740
5855
  var BsAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5741
- type: z44.literal("addArrayItem"),
5856
+ type: z44.literal("add-array-item"),
5742
5857
  arrayKey: z44.string().optional(),
5743
5858
  props: BsButtonPropsSchema.optional()
5744
5859
  });
5745
5860
  var BsRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5746
- type: z44.literal("removeArrayItem"),
5861
+ type: z44.literal("remove-array-item"),
5747
5862
  arrayKey: z44.string().optional(),
5748
5863
  props: BsButtonPropsSchema.optional()
5749
5864
  });
5865
+ var BsPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5866
+ type: z44.literal("prepend-array-item"),
5867
+ arrayKey: z44.string().optional(),
5868
+ props: BsButtonPropsSchema.optional()
5869
+ });
5870
+ var BsInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5871
+ type: z44.literal("insert-array-item"),
5872
+ arrayKey: z44.string().optional(),
5873
+ index: z44.number(),
5874
+ props: BsButtonPropsSchema.optional()
5875
+ });
5876
+ var BsPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5877
+ type: z44.literal("pop-array-item"),
5878
+ arrayKey: z44.string(),
5879
+ props: BsButtonPropsSchema.optional()
5880
+ });
5881
+ var BsShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5882
+ type: z44.literal("shift-array-item"),
5883
+ arrayKey: z44.string(),
5884
+ props: BsButtonPropsSchema.optional()
5885
+ });
5750
5886
 
5751
5887
  // internal/dynamic-forms-zod/bootstrap/src/bs-leaf-field.schema.ts
5752
5888
  import { z as z45 } from "zod";
@@ -5767,7 +5903,11 @@ var BsLeafFieldSchema = z45.discriminatedUnion("type", [
5767
5903
  BsNextButtonFieldSchema,
5768
5904
  BsPreviousButtonFieldSchema,
5769
5905
  BsAddArrayItemButtonFieldSchema,
5770
- BsRemoveArrayItemButtonFieldSchema
5906
+ BsRemoveArrayItemButtonFieldSchema,
5907
+ BsPrependArrayItemButtonFieldSchema,
5908
+ BsInsertArrayItemButtonFieldSchema,
5909
+ BsPopArrayItemButtonFieldSchema,
5910
+ BsShiftArrayItemButtonFieldSchema
5771
5911
  ]).superRefine(nullableValueRefine);
5772
5912
 
5773
5913
  // internal/dynamic-forms-zod/bootstrap/src/bs-form-config.schema.ts
@@ -5950,15 +6090,36 @@ var PrimePreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5950
6090
  props: PrimeButtonPropsSchema.optional()
5951
6091
  });
5952
6092
  var PrimeAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5953
- type: z48.literal("addArrayItem"),
6093
+ type: z48.literal("add-array-item"),
5954
6094
  arrayKey: z48.string().optional(),
5955
6095
  props: PrimeButtonPropsSchema.optional()
5956
6096
  });
5957
6097
  var PrimeRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5958
- type: z48.literal("removeArrayItem"),
6098
+ type: z48.literal("remove-array-item"),
6099
+ arrayKey: z48.string().optional(),
6100
+ props: PrimeButtonPropsSchema.optional()
6101
+ });
6102
+ var PrimePrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6103
+ type: z48.literal("prepend-array-item"),
5959
6104
  arrayKey: z48.string().optional(),
5960
6105
  props: PrimeButtonPropsSchema.optional()
5961
6106
  });
6107
+ var PrimeInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6108
+ type: z48.literal("insert-array-item"),
6109
+ arrayKey: z48.string().optional(),
6110
+ index: z48.number(),
6111
+ props: PrimeButtonPropsSchema.optional()
6112
+ });
6113
+ var PrimePopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6114
+ type: z48.literal("pop-array-item"),
6115
+ arrayKey: z48.string(),
6116
+ props: PrimeButtonPropsSchema.optional()
6117
+ });
6118
+ var PrimeShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6119
+ type: z48.literal("shift-array-item"),
6120
+ arrayKey: z48.string(),
6121
+ props: PrimeButtonPropsSchema.optional()
6122
+ });
5962
6123
 
5963
6124
  // internal/dynamic-forms-zod/primeng/src/prime-leaf-field.schema.ts
5964
6125
  import { z as z49 } from "zod";
@@ -5979,7 +6140,11 @@ var PrimeLeafFieldSchema = z49.discriminatedUnion("type", [
5979
6140
  PrimeNextButtonFieldSchema,
5980
6141
  PrimePreviousButtonFieldSchema,
5981
6142
  PrimeAddArrayItemButtonFieldSchema,
5982
- PrimeRemoveArrayItemButtonFieldSchema
6143
+ PrimeRemoveArrayItemButtonFieldSchema,
6144
+ PrimePrependArrayItemButtonFieldSchema,
6145
+ PrimeInsertArrayItemButtonFieldSchema,
6146
+ PrimePopArrayItemButtonFieldSchema,
6147
+ PrimeShiftArrayItemButtonFieldSchema
5983
6148
  ]).superRefine(nullableValueRefine);
5984
6149
 
5985
6150
  // internal/dynamic-forms-zod/primeng/src/prime-form-config.schema.ts
@@ -6204,13 +6369,34 @@ var IonicPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
6204
6369
  props: IonicButtonPropsSchema.optional()
6205
6370
  });
6206
6371
  var IonicAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6207
- type: z52.literal("addArrayItem"),
6372
+ type: z52.literal("add-array-item"),
6208
6373
  arrayKey: z52.string().optional(),
6209
6374
  props: IonicButtonPropsSchema.optional()
6210
6375
  });
6211
6376
  var IonicRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6212
- type: z52.literal("removeArrayItem"),
6377
+ type: z52.literal("remove-array-item"),
6378
+ arrayKey: z52.string().optional(),
6379
+ props: IonicButtonPropsSchema.optional()
6380
+ });
6381
+ var IonicPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6382
+ type: z52.literal("prepend-array-item"),
6383
+ arrayKey: z52.string().optional(),
6384
+ props: IonicButtonPropsSchema.optional()
6385
+ });
6386
+ var IonicInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6387
+ type: z52.literal("insert-array-item"),
6213
6388
  arrayKey: z52.string().optional(),
6389
+ index: z52.number(),
6390
+ props: IonicButtonPropsSchema.optional()
6391
+ });
6392
+ var IonicPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6393
+ type: z52.literal("pop-array-item"),
6394
+ arrayKey: z52.string(),
6395
+ props: IonicButtonPropsSchema.optional()
6396
+ });
6397
+ var IonicShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6398
+ type: z52.literal("shift-array-item"),
6399
+ arrayKey: z52.string(),
6214
6400
  props: IonicButtonPropsSchema.optional()
6215
6401
  });
6216
6402
 
@@ -6233,7 +6419,11 @@ var IonicLeafFieldSchema = z53.discriminatedUnion("type", [
6233
6419
  IonicNextButtonFieldSchema,
6234
6420
  IonicPreviousButtonFieldSchema,
6235
6421
  IonicAddArrayItemButtonFieldSchema,
6236
- IonicRemoveArrayItemButtonFieldSchema
6422
+ IonicRemoveArrayItemButtonFieldSchema,
6423
+ IonicPrependArrayItemButtonFieldSchema,
6424
+ IonicInsertArrayItemButtonFieldSchema,
6425
+ IonicPopArrayItemButtonFieldSchema,
6426
+ IonicShiftArrayItemButtonFieldSchema
6237
6427
  ]).superRefine(nullableValueRefine);
6238
6428
 
6239
6429
  // internal/dynamic-forms-zod/ionic/src/ionic-form-config.schema.ts
@@ -6578,8 +6768,12 @@ var NESTING_RULES = {
6578
6768
  "submit",
6579
6769
  "next",
6580
6770
  "previous",
6581
- "addArrayItem",
6582
- "removeArrayItem"
6771
+ "add-array-item",
6772
+ "prepend-array-item",
6773
+ "insert-array-item",
6774
+ "remove-array-item",
6775
+ "pop-array-item",
6776
+ "shift-array-item"
6583
6777
  ],
6584
6778
  forbidden: ["page"],
6585
6779
  message: "Pages cannot be nested inside other containers. ALL top-level fields must be pages if using multi-page mode."
@@ -6602,8 +6796,12 @@ var NESTING_RULES = {
6602
6796
  "submit",
6603
6797
  "next",
6604
6798
  "previous",
6605
- "addArrayItem",
6606
- "removeArrayItem"
6799
+ "add-array-item",
6800
+ "prepend-array-item",
6801
+ "insert-array-item",
6802
+ "remove-array-item",
6803
+ "pop-array-item",
6804
+ "shift-array-item"
6607
6805
  ],
6608
6806
  forbidden: ["page", "row", "hidden"],
6609
6807
  message: "Rows cannot contain pages, other rows, or hidden fields. Hidden fields should be at page or form level."
@@ -6626,8 +6824,12 @@ var NESTING_RULES = {
6626
6824
  "submit",
6627
6825
  "next",
6628
6826
  "previous",
6629
- "addArrayItem",
6630
- "removeArrayItem"
6827
+ "add-array-item",
6828
+ "prepend-array-item",
6829
+ "insert-array-item",
6830
+ "remove-array-item",
6831
+ "pop-array-item",
6832
+ "shift-array-item"
6631
6833
  ],
6632
6834
  forbidden: ["page", "group"],
6633
6835
  message: "Groups cannot contain pages or other groups (no nested groups)."
@@ -6651,8 +6853,12 @@ var NESTING_RULES = {
6651
6853
  "submit",
6652
6854
  "next",
6653
6855
  "previous",
6654
- "addArrayItem",
6655
- "removeArrayItem"
6856
+ "add-array-item",
6857
+ "prepend-array-item",
6858
+ "insert-array-item",
6859
+ "remove-array-item",
6860
+ "pop-array-item",
6861
+ "shift-array-item"
6656
6862
  ],
6657
6863
  forbidden: ["page", "array"],
6658
6864
  message: "Arrays cannot contain pages or other arrays (no nested arrays)."
@@ -6898,6 +7104,27 @@ function preValidateConfig(config) {
6898
7104
  });
6899
7105
  return errors;
6900
7106
  }
7107
+ var LEGACY_ARRAY_ACTION_TYPES = {
7108
+ addArrayItem: "add-array-item",
7109
+ prependArrayItem: "prepend-array-item",
7110
+ insertArrayItem: "insert-array-item",
7111
+ removeArrayItem: "remove-array-item",
7112
+ popArrayItem: "pop-array-item",
7113
+ shiftArrayItem: "shift-array-item"
7114
+ };
7115
+ function normalizeLegacyArrayActionTypes(value) {
7116
+ if (Array.isArray(value)) {
7117
+ return value.map(normalizeLegacyArrayActionTypes);
7118
+ }
7119
+ if (value && typeof value === "object") {
7120
+ const out = {};
7121
+ for (const [key, val] of Object.entries(value)) {
7122
+ out[key] = key === "type" && typeof val === "string" && LEGACY_ARRAY_ACTION_TYPES[val] ? LEGACY_ARRAY_ACTION_TYPES[val] : normalizeLegacyArrayActionTypes(val);
7123
+ }
7124
+ return out;
7125
+ }
7126
+ return value;
7127
+ }
6901
7128
  function validateFormConfig(uiIntegration, config) {
6902
7129
  const schema = formConfigSchemas[uiIntegration];
6903
7130
  if (!schema) {
@@ -6912,15 +7139,16 @@ function validateFormConfig(uiIntegration, config) {
6912
7139
  errorSummary: `Unknown UI integration: ${uiIntegration}`
6913
7140
  };
6914
7141
  }
6915
- const preErrors = preValidateConfig(config);
6916
- const result = schema.safeParse(config);
7142
+ const normalizedConfig = normalizeLegacyArrayActionTypes(config);
7143
+ const preErrors = preValidateConfig(normalizedConfig);
7144
+ const result = schema.safeParse(normalizedConfig);
6917
7145
  if (result.success && preErrors.length === 0) {
6918
7146
  return {
6919
7147
  valid: true,
6920
7148
  data: result.data
6921
7149
  };
6922
7150
  }
6923
- const zodErrors = result.success ? [] : formatZodError(result.error, config);
7151
+ const zodErrors = result.success ? [] : formatZodError(result.error, normalizedConfig);
6924
7152
  const allErrors = [...preErrors, ...zodErrors];
6925
7153
  return {
6926
7154
  valid: false,
@@ -6947,29 +7175,32 @@ ${UI_INTEGRATIONS.map((ui) => `- ${ui}`).join("\n")}
6947
7175
  ## Field Types
6948
7176
  ${fieldTypes.map((ft) => `- ${ft}`).join("\n")}
6949
7177
 
6950
- ## Tools (4 total - consolidated)
7178
+ ## Tools (5 total - consolidated)
6951
7179
 
6952
- **1. START HERE - One-shot reference:**
6953
- \`ngforge_get_cheatsheet(uiIntegration?)\`
7180
+ **1. START HERE - Documentation lookup:**
7181
+ \`ngforge_lookup(topic, depth?, uiIntegration?)\`
7182
+ - topic="workflow" for the recommended tool-usage guide
6954
7183
  - Property placement rules, condition syntax, copy-paste patterns, common errors
6955
- - Component API (template binding, event names)
6956
- - **Use this first** - it has 90% of what you need in one call
7184
+ - depth="brief|full|schema" (default full); uiIntegration filters schema output
6957
7185
 
6958
- **2. Validation:**
6959
- \`ngforge_validate_form_config(uiIntegration, config)\`
7186
+ **2. Search:**
7187
+ \`ngforge_search(query)\`
7188
+ - Free-text keyword search across all topics and examples
7189
+ - Use when you don't know the exact topic name
7190
+
7191
+ **3. Validation:**
7192
+ \`ngforge_validate(config, uiIntegration?)\`
6960
7193
  - Validates config against actual TypeScript types
6961
7194
  - Catches errors before runtime
6962
7195
 
6963
- **3. Field info + schema:**
6964
- \`ngforge_get_field_info(fieldType?, uiIntegration?, includeSchema?)\`
6965
- - Properties, validators, and examples for a specific field type
6966
- - Set includeSchema=true for JSON Schema (machine-readable)
6967
-
6968
- **4. Examples + deep explanations:**
6969
- \`ngforge_get_example(pattern?, depth?)\`
7196
+ **4. Examples:**
7197
+ \`ngforge_examples(pattern, depth?)\`
6970
7198
  - Patterns: complete, derivation, conditional, multi-page, validation
6971
- - depth="example" (default) = working code
6972
- - depth="deep" = conceptual explanation + code + edge cases
7199
+ - depth controls how much detail (working code vs. deep explanation)
7200
+
7201
+ **5. Scaffold:**
7202
+ \`ngforge_scaffold(fields?, pages?, arrays?, groups?, hidden?, uiIntegration?)\`
7203
+ - Generates a compilable FormConfig skeleton
6973
7204
  `
6974
7205
  }
6975
7206
  ]
@@ -7629,8 +7860,8 @@ interface SimplifiedArrayField {
7629
7860
 
7630
7861
  The simplified API is normalized into the full API at runtime:
7631
7862
  1. Each \`value\` element creates an item using the \`template\` structure
7632
- 2. An \`addArrayItem\` button is auto-generated after the array (unless \`addButton: false\`)
7633
- 3. A \`removeArrayItem\` button is added to each item (unless \`removeButton: false\`)
7863
+ 2. An \`add-array-item\` button is auto-generated after the array (unless \`addButton: false\`)
7864
+ 3. A \`remove-array-item\` button is added to each item (unless \`removeButton: false\`)
7634
7865
 
7635
7866
  ## Conditional Visibility
7636
7867
 
@@ -7844,6 +8075,7 @@ logic: [{ type: 'derivation', functionName: 'computeFromGroup', dependsOn: ['$gr
7844
8075
  \`\`\`
7845
8076
  Derivation is always defined ON the field that receives the computed value (self-targeting).
7846
8077
  \`dependsOn\` paths are absolute from the form root (e.g. \`'address.state'\`). Use \`'$self'\` for the field's own absolute path and \`'$group'\` for its nearest parent group/array \u2014 both useful in factory-built fields where ancestor keys aren't known at config time.
8078
+ **Scoping:** in derivation expressions, \`formValue\` is scoped to the parent group for group-nested fields and to the current item inside arrays, so siblings are referenced directly (e.g. \`formValue.firstName\` inside a \`person\` group). Use \`rootFormValue\` to reach fields outside the current scope.
7847
8079
  **Variables:** \`formValue\`, \`fieldValue\`, \`fieldState\`, \`formFieldState\`, \`externalData\` (see topic: expression-variables)
7848
8080
  **For deriving component properties** (minDate, options, label): use \`targetProperty\` (see topic \`property-derivation\`)`,
7849
8081
  full: `# Value Derivation (Computed Fields)
@@ -8205,7 +8437,8 @@ Wrong: Wrong property names
8205
8437
 
8206
8438
  | Variable | Type | Available In | Description |
8207
8439
  |----------|------|--------------|-------------|
8208
- | \`formValue\` | object | Derivations, conditions, custom validators | Complete form values as nested object |
8440
+ | \`formValue\` | object | Derivations, conditions, custom validators | Form values as nested object. Scoped to the current array item in array contexts; in derivations additionally scoped to the parent group for group-nested fields. Conditions on group-nested fields see the root form value |
8441
+ | \`rootFormValue\` | object | Scoped contexts (array items, group-nested derivations) | The whole form value when \`formValue\` is scoped |
8209
8442
  | \`fieldValue\` | any | Custom validator expressions only | Current field's value |
8210
8443
  | \`fieldState\` | object | Derivations, conditions | Current field's state (touched, dirty, valid, etc.) |
8211
8444
  | \`formFieldState\` | object | Derivations, conditions | All fields' states keyed by field key |
@@ -9383,19 +9616,19 @@ const config = { fields: [...] } as const satisfies FormConfig;
9383
9616
  - Together they give you: type safety + exact type inference`
9384
9617
  },
9385
9618
  "array-buttons": {
9386
- brief: `**Add:** \`{ type: 'addArrayItem', key: 'add', label: 'Add', arrayKey: 'contacts' }\`
9387
- **Remove:** \`{ type: 'removeArrayItem', key: 'remove', label: 'Remove' }\` (inside array template)
9619
+ brief: `**Add:** \`{ type: 'add-array-item', key: 'add', label: 'Add', arrayKey: 'contacts' }\`
9620
+ **Remove:** \`{ type: 'remove-array-item', key: 'remove', label: 'Remove' }\` (inside array template)
9388
9621
  \u26A0\uFE0F arrayKey at FIELD level, NOT in props!`,
9389
9622
  full: `# Array Buttons (Add/Remove Items)
9390
9623
 
9391
- **UI libraries provide \`addArrayItem\` and \`removeArrayItem\` button types.**
9624
+ **UI libraries provide \`add-array-item\` and \`remove-array-item\` button types.**
9392
9625
 
9393
9626
  ## Add Item Button
9394
9627
 
9395
9628
  \`\`\`typescript
9396
9629
  {
9397
9630
  key: 'addPhone',
9398
- type: 'addArrayItem',
9631
+ type: 'add-array-item',
9399
9632
  label: 'Add Phone',
9400
9633
  arrayKey: 'phones', // \u26A0\uFE0F AT FIELD LEVEL, NOT IN PROPS!
9401
9634
  props: {
@@ -9417,7 +9650,7 @@ const config = { fields: [...] } as const satisfies FormConfig;
9417
9650
  { key: 'number', type: 'input', label: 'Phone Number' },
9418
9651
  {
9419
9652
  key: 'removePhone',
9420
- type: 'removeArrayItem',
9653
+ type: 'remove-array-item',
9421
9654
  label: 'Remove',
9422
9655
  // arrayKey not needed - inferred from parent array
9423
9656
  props: { color: 'warn' }
@@ -9432,13 +9665,13 @@ const config = { fields: [...] } as const satisfies FormConfig;
9432
9665
  \`\`\`typescript
9433
9666
  // WRONG - arrayKey in props
9434
9667
  {
9435
- type: 'addArrayItem',
9668
+ type: 'add-array-item',
9436
9669
  props: { arrayKey: 'phones' } // \u274C WRONG LOCATION
9437
9670
  }
9438
9671
 
9439
9672
  // CORRECT - arrayKey at field level
9440
9673
  {
9441
- type: 'addArrayItem',
9674
+ type: 'add-array-item',
9442
9675
  arrayKey: 'phones', // \u2705 CORRECT
9443
9676
  props: { color: 'primary' }
9444
9677
  }
@@ -9707,8 +9940,19 @@ var TOPIC_ALIASES = {
9707
9940
  valueof: "context-api",
9708
9941
  "add-array": "array-buttons",
9709
9942
  "remove-array": "array-buttons",
9943
+ // Array-action field types: kebab-case canonical + camelCase legacy aliases
9944
+ "add-array-item": "array-buttons",
9945
+ "prepend-array-item": "array-buttons",
9946
+ "insert-array-item": "array-buttons",
9947
+ "remove-array-item": "array-buttons",
9948
+ "pop-array-item": "array-buttons",
9949
+ "shift-array-item": "array-buttons",
9710
9950
  addarrayitem: "array-buttons",
9951
+ prependarrayitem: "array-buttons",
9952
+ insertarrayitem: "array-buttons",
9711
9953
  removearrayitem: "array-buttons",
9954
+ poparrayitem: "array-buttons",
9955
+ shiftarrayitem: "array-buttons",
9712
9956
  "custom-validator": "custom-validators",
9713
9957
  customvalidator: "custom-validators",
9714
9958
  mistakes: "pitfalls",
@@ -10753,7 +10997,7 @@ For full control, use the \`fields\`-based API with explicit add/remove buttons:
10753
10997
  ]
10754
10998
  ]
10755
10999
  }
10756
- // + separate addArrayItem button with arrayKey
11000
+ // + separate add-array-item button with arrayKey
10757
11001
  \`\`\``,
10758
11002
  explained: `# Array Fields - Complete Explanation
10759
11003
 
@@ -10825,7 +11069,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10825
11069
  // ADD button - place OUTSIDE the array
10826
11070
  {
10827
11071
  key: 'addContact',
10828
- type: 'addArrayItem',
11072
+ type: 'add-array-item',
10829
11073
  label: 'Add Contact',
10830
11074
  arrayKey: 'contacts', // \u26A0\uFE0F AT FIELD LEVEL!
10831
11075
  }
@@ -10837,7 +11081,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10837
11081
  fields: [
10838
11082
  [
10839
11083
  { key: 'name', type: 'input', label: 'Name' },
10840
- { key: 'remove', type: 'removeArrayItem', label: 'Remove' }
11084
+ { key: 'remove', type: 'remove-array-item', label: 'Remove' }
10841
11085
  ]
10842
11086
  ]
10843
11087
  }
@@ -10871,8 +11115,8 @@ expression: '(formValue.items || []).reduce((sum, item) => sum + (item.price ||
10871
11115
 
10872
11116
  \u274C Putting \`arrayKey\` in props (full API):
10873
11117
  \`\`\`typescript
10874
- { type: 'addArrayItem', props: { arrayKey: 'x' } } // WRONG
10875
- { type: 'addArrayItem', arrayKey: 'x' } // CORRECT
11118
+ { type: 'add-array-item', props: { arrayKey: 'x' } } // WRONG
11119
+ { type: 'add-array-item', arrayKey: 'x' } // CORRECT
10876
11120
  \`\`\``
10877
11121
  },
10878
11122
  "minimal-simplified-array": {