@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.
package/src/index.js CHANGED
@@ -648,9 +648,9 @@ var FIELD_TYPES = [
648
648
  minimalExample: `{ key: 'submit', type: 'submit', label: 'Submit' }`
649
649
  },
650
650
  {
651
- type: "addArrayItem",
651
+ type: "add-array-item",
652
652
  category: "button",
653
- description: "Button to add a new item to an array field. Must be placed within or near the array container.",
653
+ 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.)",
654
654
  valueType: void 0,
655
655
  baseInterface: "FieldDef",
656
656
  props: {},
@@ -659,15 +659,50 @@ var FIELD_TYPES = [
659
659
  allowedIn: ["array", "row", "group"],
660
660
  example: `{
661
661
  key: 'addContact',
662
- type: 'addArrayItem',
662
+ type: 'add-array-item',
663
663
  label: 'Add Contact'
664
664
  }`,
665
- minimalExample: `{ key: 'add', type: 'addArrayItem', label: 'Add Item' }`
665
+ minimalExample: `{ key: 'add', type: 'add-array-item', label: 'Add Item' }`
666
666
  },
667
667
  {
668
- type: "removeArrayItem",
668
+ type: "prepend-array-item",
669
669
  category: "button",
670
- description: "Button to remove the current item from an array field. Typically placed within each array item template.",
670
+ description: "Button to add a new item to the beginning of an array field. (Legacy alias: prependArrayItem.)",
671
+ valueType: void 0,
672
+ baseInterface: "FieldDef",
673
+ props: {},
674
+ validationSupported: false,
675
+ source: "adapter",
676
+ allowedIn: ["array", "row", "group"],
677
+ example: `{
678
+ key: 'prependContact',
679
+ type: 'prepend-array-item',
680
+ label: 'Add to Top'
681
+ }`,
682
+ minimalExample: `{ key: 'prepend', type: 'prepend-array-item', label: 'Add First' }`
683
+ },
684
+ {
685
+ type: "insert-array-item",
686
+ category: "button",
687
+ description: "Button to insert a new item at a specific index in an array field (set via the index property). (Legacy alias: insertArrayItem.)",
688
+ valueType: void 0,
689
+ baseInterface: "FieldDef",
690
+ props: {},
691
+ validationSupported: false,
692
+ source: "adapter",
693
+ allowedIn: ["array", "row", "group"],
694
+ example: `{
695
+ key: 'insertContact',
696
+ type: 'insert-array-item',
697
+ label: 'Insert',
698
+ index: 1
699
+ }`,
700
+ minimalExample: `{ key: 'insert', type: 'insert-array-item', label: 'Insert', index: 0 }`
701
+ },
702
+ {
703
+ type: "remove-array-item",
704
+ category: "button",
705
+ description: "Button to remove the current item from an array field. Typically placed within each array item template. (Legacy alias: removeArrayItem.)",
671
706
  valueType: void 0,
672
707
  baseInterface: "FieldDef",
673
708
  props: {},
@@ -676,10 +711,46 @@ var FIELD_TYPES = [
676
711
  allowedIn: ["array", "row", "group"],
677
712
  example: `{
678
713
  key: 'removeContact',
679
- type: 'removeArrayItem',
714
+ type: 'remove-array-item',
680
715
  label: 'Remove'
681
716
  }`,
682
- minimalExample: `{ key: 'remove', type: 'removeArrayItem', label: 'Remove' }`
717
+ minimalExample: `{ key: 'remove', type: 'remove-array-item', label: 'Remove' }`
718
+ },
719
+ {
720
+ type: "pop-array-item",
721
+ category: "button",
722
+ description: "Button to remove the last item from an array field. (Legacy alias: popArrayItem.)",
723
+ valueType: void 0,
724
+ baseInterface: "FieldDef",
725
+ props: {},
726
+ validationSupported: false,
727
+ source: "adapter",
728
+ allowedIn: ["array", "row", "group"],
729
+ example: `{
730
+ key: 'popContact',
731
+ type: 'pop-array-item',
732
+ label: 'Remove Last',
733
+ arrayKey: 'contacts'
734
+ }`,
735
+ minimalExample: `{ key: 'pop', type: 'pop-array-item', label: 'Remove Last', arrayKey: 'items' }`
736
+ },
737
+ {
738
+ type: "shift-array-item",
739
+ category: "button",
740
+ description: "Button to remove the first item from an array field. (Legacy alias: shiftArrayItem.)",
741
+ valueType: void 0,
742
+ baseInterface: "FieldDef",
743
+ props: {},
744
+ validationSupported: false,
745
+ source: "adapter",
746
+ allowedIn: ["array", "row", "group"],
747
+ example: `{
748
+ key: 'shiftContact',
749
+ type: 'shift-array-item',
750
+ label: 'Remove First',
751
+ arrayKey: 'contacts'
752
+ }`,
753
+ minimalExample: `{ key: 'shift', type: 'shift-array-item', label: 'Remove First', arrayKey: 'items' }`
683
754
  }
684
755
  ];
685
756
 
@@ -1470,7 +1541,7 @@ var WRAPPERS = [
1470
1541
  category: "demo",
1471
1542
  availability: "demo-only",
1472
1543
  package: "@internal/examples-shared-ui",
1473
- 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.',
1544
+ 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.',
1474
1545
  props: {
1475
1546
  title: {
1476
1547
  name: "title",
@@ -2858,6 +2929,8 @@ Evaluates a JavaScript expression with access to \`formValue\`, \`fieldValue\`,
2858
2929
  }
2859
2930
  \`\`\`
2860
2931
 
2932
+ **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.
2933
+
2861
2934
  #### Custom Condition
2862
2935
 
2863
2936
  Invokes a registered custom function by name:
@@ -3035,7 +3108,7 @@ All features are exported from \`@ng-forge/dynamic-forms\`.
3035
3108
 
3036
3109
  ## CRITICAL: UI Library Differences
3037
3110
 
3038
- Different UI libraries support different properties. Always validate against the correct library using \`ngforge_validate_form_config\` with the appropriate \`uiIntegration\` parameter.
3111
+ Different UI libraries support different properties. Always validate against the correct library using \`ngforge_validate\` with the appropriate \`uiIntegration\` parameter.
3039
3112
 
3040
3113
  ### Property Differences by Library
3041
3114
 
@@ -3078,24 +3151,24 @@ Container fields (\`page\`, \`group\`, \`row\`) do NOT support these properties:
3078
3151
  { key: 'volume', type: 'slider', label: 'Volume', min: 0, max: 100 }
3079
3152
  \`\`\`
3080
3153
 
3081
- 5. **Using unsupported field types** - Each UI library supports specific field types. Use \`ngforge_get_field_schema\` to see available types.
3154
+ 5. **Using unsupported field types** - Each UI library supports specific field types. Use \`ngforge_lookup\` with \`depth: "schema"\` to see available types.
3082
3155
 
3083
3156
  ## Validation Before Use
3084
3157
 
3085
- 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.
3158
+ 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.
3086
3159
 
3087
3160
  \`\`\`typescript
3088
3161
  // Always specify the UI integration you're using
3089
- ngforge_validate_form_config({
3162
+ ngforge_validate({
3090
3163
  uiIntegration: 'material', // or 'bootstrap', 'primeng', 'ionic'
3091
3164
  config: { fields: [...] }
3092
3165
  })
3093
3166
  \`\`\`
3094
3167
 
3095
- To understand what properties are supported for each field type, use \`ngforge_get_field_schema\`:
3168
+ To understand what properties are supported for each field type, use \`ngforge_lookup\` with \`depth: "schema"\`:
3096
3169
 
3097
3170
  \`\`\`typescript
3098
- ngforge_get_field_schema({ uiIntegration: 'material' })
3171
+ ngforge_lookup({ topic: 'input', depth: 'schema', uiIntegration: 'material' })
3099
3172
  \`\`\`
3100
3173
  `;
3101
3174
 
@@ -5211,7 +5284,7 @@ var MatPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5211
5284
  props: MatButtonPropsSchema.optional()
5212
5285
  });
5213
5286
  var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5214
- type: z33.literal("addArrayItem"),
5287
+ type: z33.literal("add-array-item"),
5215
5288
  /**
5216
5289
  * Key of the array field to add items to.
5217
5290
  * If omitted, uses the parent array context.
@@ -5220,7 +5293,7 @@ var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5220
5293
  props: MatButtonPropsSchema.optional()
5221
5294
  });
5222
5295
  var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5223
- type: z33.literal("removeArrayItem"),
5296
+ type: z33.literal("remove-array-item"),
5224
5297
  /**
5225
5298
  * Key of the array field to remove items from.
5226
5299
  * If omitted, uses the parent array context.
@@ -5228,6 +5301,44 @@ var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5228
5301
  arrayKey: z33.string().optional(),
5229
5302
  props: MatButtonPropsSchema.optional()
5230
5303
  });
5304
+ var MatPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5305
+ type: z33.literal("prepend-array-item"),
5306
+ /**
5307
+ * Key of the array field to prepend items to.
5308
+ * If omitted, uses the parent array context.
5309
+ */
5310
+ arrayKey: z33.string().optional(),
5311
+ props: MatButtonPropsSchema.optional()
5312
+ });
5313
+ var MatInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5314
+ type: z33.literal("insert-array-item"),
5315
+ /**
5316
+ * Key of the array field to insert items into.
5317
+ * If omitted, uses the parent array context.
5318
+ */
5319
+ arrayKey: z33.string().optional(),
5320
+ /**
5321
+ * Index at which to insert the new item.
5322
+ */
5323
+ index: z33.number(),
5324
+ props: MatButtonPropsSchema.optional()
5325
+ });
5326
+ var MatPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5327
+ type: z33.literal("pop-array-item"),
5328
+ /**
5329
+ * Key of the array field to pop items from.
5330
+ */
5331
+ arrayKey: z33.string(),
5332
+ props: MatButtonPropsSchema.optional()
5333
+ });
5334
+ var MatShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5335
+ type: z33.literal("shift-array-item"),
5336
+ /**
5337
+ * Key of the array field to shift items from.
5338
+ */
5339
+ arrayKey: z33.string(),
5340
+ props: MatButtonPropsSchema.optional()
5341
+ });
5231
5342
 
5232
5343
  // internal/dynamic-forms-zod/material/src/mat-leaf-field.schema.ts
5233
5344
  import { z as z36 } from "zod";
@@ -5303,7 +5414,11 @@ var MatLeafFieldSchema = z36.discriminatedUnion("type", [
5303
5414
  MatNextButtonFieldSchema,
5304
5415
  MatPreviousButtonFieldSchema,
5305
5416
  MatAddArrayItemButtonFieldSchema,
5306
- MatRemoveArrayItemButtonFieldSchema
5417
+ MatRemoveArrayItemButtonFieldSchema,
5418
+ MatPrependArrayItemButtonFieldSchema,
5419
+ MatInsertArrayItemButtonFieldSchema,
5420
+ MatPopArrayItemButtonFieldSchema,
5421
+ MatShiftArrayItemButtonFieldSchema
5307
5422
  ]).superRefine(nullableValueRefine);
5308
5423
 
5309
5424
  // internal/dynamic-forms-zod/src/lib/schemas/containers/factories.ts
@@ -5771,15 +5886,36 @@ var BsPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5771
5886
  props: BsButtonPropsSchema.optional()
5772
5887
  });
5773
5888
  var BsAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5774
- type: z44.literal("addArrayItem"),
5889
+ type: z44.literal("add-array-item"),
5775
5890
  arrayKey: z44.string().optional(),
5776
5891
  props: BsButtonPropsSchema.optional()
5777
5892
  });
5778
5893
  var BsRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5779
- type: z44.literal("removeArrayItem"),
5894
+ type: z44.literal("remove-array-item"),
5780
5895
  arrayKey: z44.string().optional(),
5781
5896
  props: BsButtonPropsSchema.optional()
5782
5897
  });
5898
+ var BsPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5899
+ type: z44.literal("prepend-array-item"),
5900
+ arrayKey: z44.string().optional(),
5901
+ props: BsButtonPropsSchema.optional()
5902
+ });
5903
+ var BsInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5904
+ type: z44.literal("insert-array-item"),
5905
+ arrayKey: z44.string().optional(),
5906
+ index: z44.number(),
5907
+ props: BsButtonPropsSchema.optional()
5908
+ });
5909
+ var BsPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5910
+ type: z44.literal("pop-array-item"),
5911
+ arrayKey: z44.string(),
5912
+ props: BsButtonPropsSchema.optional()
5913
+ });
5914
+ var BsShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5915
+ type: z44.literal("shift-array-item"),
5916
+ arrayKey: z44.string(),
5917
+ props: BsButtonPropsSchema.optional()
5918
+ });
5783
5919
 
5784
5920
  // internal/dynamic-forms-zod/bootstrap/src/bs-leaf-field.schema.ts
5785
5921
  import { z as z45 } from "zod";
@@ -5800,7 +5936,11 @@ var BsLeafFieldSchema = z45.discriminatedUnion("type", [
5800
5936
  BsNextButtonFieldSchema,
5801
5937
  BsPreviousButtonFieldSchema,
5802
5938
  BsAddArrayItemButtonFieldSchema,
5803
- BsRemoveArrayItemButtonFieldSchema
5939
+ BsRemoveArrayItemButtonFieldSchema,
5940
+ BsPrependArrayItemButtonFieldSchema,
5941
+ BsInsertArrayItemButtonFieldSchema,
5942
+ BsPopArrayItemButtonFieldSchema,
5943
+ BsShiftArrayItemButtonFieldSchema
5804
5944
  ]).superRefine(nullableValueRefine);
5805
5945
 
5806
5946
  // internal/dynamic-forms-zod/bootstrap/src/bs-form-config.schema.ts
@@ -5983,15 +6123,36 @@ var PrimePreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5983
6123
  props: PrimeButtonPropsSchema.optional()
5984
6124
  });
5985
6125
  var PrimeAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5986
- type: z48.literal("addArrayItem"),
6126
+ type: z48.literal("add-array-item"),
5987
6127
  arrayKey: z48.string().optional(),
5988
6128
  props: PrimeButtonPropsSchema.optional()
5989
6129
  });
5990
6130
  var PrimeRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5991
- type: z48.literal("removeArrayItem"),
6131
+ type: z48.literal("remove-array-item"),
6132
+ arrayKey: z48.string().optional(),
6133
+ props: PrimeButtonPropsSchema.optional()
6134
+ });
6135
+ var PrimePrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6136
+ type: z48.literal("prepend-array-item"),
5992
6137
  arrayKey: z48.string().optional(),
5993
6138
  props: PrimeButtonPropsSchema.optional()
5994
6139
  });
6140
+ var PrimeInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6141
+ type: z48.literal("insert-array-item"),
6142
+ arrayKey: z48.string().optional(),
6143
+ index: z48.number(),
6144
+ props: PrimeButtonPropsSchema.optional()
6145
+ });
6146
+ var PrimePopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6147
+ type: z48.literal("pop-array-item"),
6148
+ arrayKey: z48.string(),
6149
+ props: PrimeButtonPropsSchema.optional()
6150
+ });
6151
+ var PrimeShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6152
+ type: z48.literal("shift-array-item"),
6153
+ arrayKey: z48.string(),
6154
+ props: PrimeButtonPropsSchema.optional()
6155
+ });
5995
6156
 
5996
6157
  // internal/dynamic-forms-zod/primeng/src/prime-leaf-field.schema.ts
5997
6158
  import { z as z49 } from "zod";
@@ -6012,7 +6173,11 @@ var PrimeLeafFieldSchema = z49.discriminatedUnion("type", [
6012
6173
  PrimeNextButtonFieldSchema,
6013
6174
  PrimePreviousButtonFieldSchema,
6014
6175
  PrimeAddArrayItemButtonFieldSchema,
6015
- PrimeRemoveArrayItemButtonFieldSchema
6176
+ PrimeRemoveArrayItemButtonFieldSchema,
6177
+ PrimePrependArrayItemButtonFieldSchema,
6178
+ PrimeInsertArrayItemButtonFieldSchema,
6179
+ PrimePopArrayItemButtonFieldSchema,
6180
+ PrimeShiftArrayItemButtonFieldSchema
6016
6181
  ]).superRefine(nullableValueRefine);
6017
6182
 
6018
6183
  // internal/dynamic-forms-zod/primeng/src/prime-form-config.schema.ts
@@ -6237,13 +6402,34 @@ var IonicPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
6237
6402
  props: IonicButtonPropsSchema.optional()
6238
6403
  });
6239
6404
  var IonicAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6240
- type: z52.literal("addArrayItem"),
6405
+ type: z52.literal("add-array-item"),
6241
6406
  arrayKey: z52.string().optional(),
6242
6407
  props: IonicButtonPropsSchema.optional()
6243
6408
  });
6244
6409
  var IonicRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6245
- type: z52.literal("removeArrayItem"),
6410
+ type: z52.literal("remove-array-item"),
6411
+ arrayKey: z52.string().optional(),
6412
+ props: IonicButtonPropsSchema.optional()
6413
+ });
6414
+ var IonicPrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6415
+ type: z52.literal("prepend-array-item"),
6416
+ arrayKey: z52.string().optional(),
6417
+ props: IonicButtonPropsSchema.optional()
6418
+ });
6419
+ var IonicInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6420
+ type: z52.literal("insert-array-item"),
6246
6421
  arrayKey: z52.string().optional(),
6422
+ index: z52.number(),
6423
+ props: IonicButtonPropsSchema.optional()
6424
+ });
6425
+ var IonicPopArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6426
+ type: z52.literal("pop-array-item"),
6427
+ arrayKey: z52.string(),
6428
+ props: IonicButtonPropsSchema.optional()
6429
+ });
6430
+ var IonicShiftArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6431
+ type: z52.literal("shift-array-item"),
6432
+ arrayKey: z52.string(),
6247
6433
  props: IonicButtonPropsSchema.optional()
6248
6434
  });
6249
6435
 
@@ -6266,7 +6452,11 @@ var IonicLeafFieldSchema = z53.discriminatedUnion("type", [
6266
6452
  IonicNextButtonFieldSchema,
6267
6453
  IonicPreviousButtonFieldSchema,
6268
6454
  IonicAddArrayItemButtonFieldSchema,
6269
- IonicRemoveArrayItemButtonFieldSchema
6455
+ IonicRemoveArrayItemButtonFieldSchema,
6456
+ IonicPrependArrayItemButtonFieldSchema,
6457
+ IonicInsertArrayItemButtonFieldSchema,
6458
+ IonicPopArrayItemButtonFieldSchema,
6459
+ IonicShiftArrayItemButtonFieldSchema
6270
6460
  ]).superRefine(nullableValueRefine);
6271
6461
 
6272
6462
  // internal/dynamic-forms-zod/ionic/src/ionic-form-config.schema.ts
@@ -6652,8 +6842,12 @@ var NESTING_RULES = {
6652
6842
  "submit",
6653
6843
  "next",
6654
6844
  "previous",
6655
- "addArrayItem",
6656
- "removeArrayItem"
6845
+ "add-array-item",
6846
+ "prepend-array-item",
6847
+ "insert-array-item",
6848
+ "remove-array-item",
6849
+ "pop-array-item",
6850
+ "shift-array-item"
6657
6851
  ],
6658
6852
  forbidden: ["page"],
6659
6853
  message: "Pages cannot be nested inside other containers. ALL top-level fields must be pages if using multi-page mode."
@@ -6676,8 +6870,12 @@ var NESTING_RULES = {
6676
6870
  "submit",
6677
6871
  "next",
6678
6872
  "previous",
6679
- "addArrayItem",
6680
- "removeArrayItem"
6873
+ "add-array-item",
6874
+ "prepend-array-item",
6875
+ "insert-array-item",
6876
+ "remove-array-item",
6877
+ "pop-array-item",
6878
+ "shift-array-item"
6681
6879
  ],
6682
6880
  forbidden: ["page", "row", "hidden"],
6683
6881
  message: "Rows cannot contain pages, other rows, or hidden fields. Hidden fields should be at page or form level."
@@ -6700,8 +6898,12 @@ var NESTING_RULES = {
6700
6898
  "submit",
6701
6899
  "next",
6702
6900
  "previous",
6703
- "addArrayItem",
6704
- "removeArrayItem"
6901
+ "add-array-item",
6902
+ "prepend-array-item",
6903
+ "insert-array-item",
6904
+ "remove-array-item",
6905
+ "pop-array-item",
6906
+ "shift-array-item"
6705
6907
  ],
6706
6908
  forbidden: ["page", "group"],
6707
6909
  message: "Groups cannot contain pages or other groups (no nested groups)."
@@ -6725,8 +6927,12 @@ var NESTING_RULES = {
6725
6927
  "submit",
6726
6928
  "next",
6727
6929
  "previous",
6728
- "addArrayItem",
6729
- "removeArrayItem"
6930
+ "add-array-item",
6931
+ "prepend-array-item",
6932
+ "insert-array-item",
6933
+ "remove-array-item",
6934
+ "pop-array-item",
6935
+ "shift-array-item"
6730
6936
  ],
6731
6937
  forbidden: ["page", "array"],
6732
6938
  message: "Arrays cannot contain pages or other arrays (no nested arrays)."
@@ -6972,6 +7178,27 @@ function preValidateConfig(config) {
6972
7178
  });
6973
7179
  return errors;
6974
7180
  }
7181
+ var LEGACY_ARRAY_ACTION_TYPES = {
7182
+ addArrayItem: "add-array-item",
7183
+ prependArrayItem: "prepend-array-item",
7184
+ insertArrayItem: "insert-array-item",
7185
+ removeArrayItem: "remove-array-item",
7186
+ popArrayItem: "pop-array-item",
7187
+ shiftArrayItem: "shift-array-item"
7188
+ };
7189
+ function normalizeLegacyArrayActionTypes(value) {
7190
+ if (Array.isArray(value)) {
7191
+ return value.map(normalizeLegacyArrayActionTypes);
7192
+ }
7193
+ if (value && typeof value === "object") {
7194
+ const out = {};
7195
+ for (const [key, val] of Object.entries(value)) {
7196
+ out[key] = key === "type" && typeof val === "string" && LEGACY_ARRAY_ACTION_TYPES[val] ? LEGACY_ARRAY_ACTION_TYPES[val] : normalizeLegacyArrayActionTypes(val);
7197
+ }
7198
+ return out;
7199
+ }
7200
+ return value;
7201
+ }
6975
7202
  function validateFormConfig(uiIntegration, config) {
6976
7203
  const schema = formConfigSchemas2[uiIntegration];
6977
7204
  if (!schema) {
@@ -6986,15 +7213,16 @@ function validateFormConfig(uiIntegration, config) {
6986
7213
  errorSummary: `Unknown UI integration: ${uiIntegration}`
6987
7214
  };
6988
7215
  }
6989
- const preErrors = preValidateConfig(config);
6990
- const result = schema.safeParse(config);
7216
+ const normalizedConfig = normalizeLegacyArrayActionTypes(config);
7217
+ const preErrors = preValidateConfig(normalizedConfig);
7218
+ const result = schema.safeParse(normalizedConfig);
6991
7219
  if (result.success && preErrors.length === 0) {
6992
7220
  return {
6993
7221
  valid: true,
6994
7222
  data: result.data
6995
7223
  };
6996
7224
  }
6997
- const zodErrors = result.success ? [] : formatZodError(result.error, config);
7225
+ const zodErrors = result.success ? [] : formatZodError(result.error, normalizedConfig);
6998
7226
  const allErrors = [...preErrors, ...zodErrors];
6999
7227
  return {
7000
7228
  valid: false,
@@ -7024,29 +7252,32 @@ ${UI_INTEGRATIONS.map((ui) => `- ${ui}`).join("\n")}
7024
7252
  ## Field Types
7025
7253
  ${fieldTypes.map((ft) => `- ${ft}`).join("\n")}
7026
7254
 
7027
- ## Tools (4 total - consolidated)
7255
+ ## Tools (5 total - consolidated)
7028
7256
 
7029
- **1. START HERE - One-shot reference:**
7030
- \`ngforge_get_cheatsheet(uiIntegration?)\`
7257
+ **1. START HERE - Documentation lookup:**
7258
+ \`ngforge_lookup(topic, depth?, uiIntegration?)\`
7259
+ - topic="workflow" for the recommended tool-usage guide
7031
7260
  - Property placement rules, condition syntax, copy-paste patterns, common errors
7032
- - Component API (template binding, event names)
7033
- - **Use this first** - it has 90% of what you need in one call
7261
+ - depth="brief|full|schema" (default full); uiIntegration filters schema output
7034
7262
 
7035
- **2. Validation:**
7036
- \`ngforge_validate_form_config(uiIntegration, config)\`
7263
+ **2. Search:**
7264
+ \`ngforge_search(query)\`
7265
+ - Free-text keyword search across all topics and examples
7266
+ - Use when you don't know the exact topic name
7267
+
7268
+ **3. Validation:**
7269
+ \`ngforge_validate(config, uiIntegration?)\`
7037
7270
  - Validates config against actual TypeScript types
7038
7271
  - Catches errors before runtime
7039
7272
 
7040
- **3. Field info + schema:**
7041
- \`ngforge_get_field_info(fieldType?, uiIntegration?, includeSchema?)\`
7042
- - Properties, validators, and examples for a specific field type
7043
- - Set includeSchema=true for JSON Schema (machine-readable)
7044
-
7045
- **4. Examples + deep explanations:**
7046
- \`ngforge_get_example(pattern?, depth?)\`
7273
+ **4. Examples:**
7274
+ \`ngforge_examples(pattern, depth?)\`
7047
7275
  - Patterns: complete, derivation, conditional, multi-page, validation
7048
- - depth="example" (default) = working code
7049
- - depth="deep" = conceptual explanation + code + edge cases
7276
+ - depth controls how much detail (working code vs. deep explanation)
7277
+
7278
+ **5. Scaffold:**
7279
+ \`ngforge_scaffold(fields?, pages?, arrays?, groups?, hidden?, uiIntegration?)\`
7280
+ - Generates a compilable FormConfig skeleton
7050
7281
  `
7051
7282
  }
7052
7283
  ]
@@ -7706,8 +7937,8 @@ interface SimplifiedArrayField {
7706
7937
 
7707
7938
  The simplified API is normalized into the full API at runtime:
7708
7939
  1. Each \`value\` element creates an item using the \`template\` structure
7709
- 2. An \`addArrayItem\` button is auto-generated after the array (unless \`addButton: false\`)
7710
- 3. A \`removeArrayItem\` button is added to each item (unless \`removeButton: false\`)
7940
+ 2. An \`add-array-item\` button is auto-generated after the array (unless \`addButton: false\`)
7941
+ 3. A \`remove-array-item\` button is added to each item (unless \`removeButton: false\`)
7711
7942
 
7712
7943
  ## Conditional Visibility
7713
7944
 
@@ -7921,6 +8152,7 @@ logic: [{ type: 'derivation', functionName: 'computeFromGroup', dependsOn: ['$gr
7921
8152
  \`\`\`
7922
8153
  Derivation is always defined ON the field that receives the computed value (self-targeting).
7923
8154
  \`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.
8155
+ **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.
7924
8156
  **Variables:** \`formValue\`, \`fieldValue\`, \`fieldState\`, \`formFieldState\`, \`externalData\` (see topic: expression-variables)
7925
8157
  **For deriving component properties** (minDate, options, label): use \`targetProperty\` (see topic \`property-derivation\`)`,
7926
8158
  full: `# Value Derivation (Computed Fields)
@@ -8282,7 +8514,8 @@ Wrong: Wrong property names
8282
8514
 
8283
8515
  | Variable | Type | Available In | Description |
8284
8516
  |----------|------|--------------|-------------|
8285
- | \`formValue\` | object | Derivations, conditions, custom validators | Complete form values as nested object |
8517
+ | \`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 |
8518
+ | \`rootFormValue\` | object | Scoped contexts (array items, group-nested derivations) | The whole form value when \`formValue\` is scoped |
8286
8519
  | \`fieldValue\` | any | Custom validator expressions only | Current field's value |
8287
8520
  | \`fieldState\` | object | Derivations, conditions | Current field's state (touched, dirty, valid, etc.) |
8288
8521
  | \`formFieldState\` | object | Derivations, conditions | All fields' states keyed by field key |
@@ -9460,19 +9693,19 @@ const config = { fields: [...] } as const satisfies FormConfig;
9460
9693
  - Together they give you: type safety + exact type inference`
9461
9694
  },
9462
9695
  "array-buttons": {
9463
- brief: `**Add:** \`{ type: 'addArrayItem', key: 'add', label: 'Add', arrayKey: 'contacts' }\`
9464
- **Remove:** \`{ type: 'removeArrayItem', key: 'remove', label: 'Remove' }\` (inside array template)
9696
+ brief: `**Add:** \`{ type: 'add-array-item', key: 'add', label: 'Add', arrayKey: 'contacts' }\`
9697
+ **Remove:** \`{ type: 'remove-array-item', key: 'remove', label: 'Remove' }\` (inside array template)
9465
9698
  \u26A0\uFE0F arrayKey at FIELD level, NOT in props!`,
9466
9699
  full: `# Array Buttons (Add/Remove Items)
9467
9700
 
9468
- **UI libraries provide \`addArrayItem\` and \`removeArrayItem\` button types.**
9701
+ **UI libraries provide \`add-array-item\` and \`remove-array-item\` button types.**
9469
9702
 
9470
9703
  ## Add Item Button
9471
9704
 
9472
9705
  \`\`\`typescript
9473
9706
  {
9474
9707
  key: 'addPhone',
9475
- type: 'addArrayItem',
9708
+ type: 'add-array-item',
9476
9709
  label: 'Add Phone',
9477
9710
  arrayKey: 'phones', // \u26A0\uFE0F AT FIELD LEVEL, NOT IN PROPS!
9478
9711
  props: {
@@ -9494,7 +9727,7 @@ const config = { fields: [...] } as const satisfies FormConfig;
9494
9727
  { key: 'number', type: 'input', label: 'Phone Number' },
9495
9728
  {
9496
9729
  key: 'removePhone',
9497
- type: 'removeArrayItem',
9730
+ type: 'remove-array-item',
9498
9731
  label: 'Remove',
9499
9732
  // arrayKey not needed - inferred from parent array
9500
9733
  props: { color: 'warn' }
@@ -9509,13 +9742,13 @@ const config = { fields: [...] } as const satisfies FormConfig;
9509
9742
  \`\`\`typescript
9510
9743
  // WRONG - arrayKey in props
9511
9744
  {
9512
- type: 'addArrayItem',
9745
+ type: 'add-array-item',
9513
9746
  props: { arrayKey: 'phones' } // \u274C WRONG LOCATION
9514
9747
  }
9515
9748
 
9516
9749
  // CORRECT - arrayKey at field level
9517
9750
  {
9518
- type: 'addArrayItem',
9751
+ type: 'add-array-item',
9519
9752
  arrayKey: 'phones', // \u2705 CORRECT
9520
9753
  props: { color: 'primary' }
9521
9754
  }
@@ -9784,8 +10017,19 @@ var TOPIC_ALIASES = {
9784
10017
  valueof: "context-api",
9785
10018
  "add-array": "array-buttons",
9786
10019
  "remove-array": "array-buttons",
10020
+ // Array-action field types: kebab-case canonical + camelCase legacy aliases
10021
+ "add-array-item": "array-buttons",
10022
+ "prepend-array-item": "array-buttons",
10023
+ "insert-array-item": "array-buttons",
10024
+ "remove-array-item": "array-buttons",
10025
+ "pop-array-item": "array-buttons",
10026
+ "shift-array-item": "array-buttons",
9787
10027
  addarrayitem: "array-buttons",
10028
+ prependarrayitem: "array-buttons",
10029
+ insertarrayitem: "array-buttons",
9788
10030
  removearrayitem: "array-buttons",
10031
+ poparrayitem: "array-buttons",
10032
+ shiftarrayitem: "array-buttons",
9789
10033
  "custom-validator": "custom-validators",
9790
10034
  customvalidator: "custom-validators",
9791
10035
  mistakes: "pitfalls",
@@ -10830,7 +11074,7 @@ For full control, use the \`fields\`-based API with explicit add/remove buttons:
10830
11074
  ]
10831
11075
  ]
10832
11076
  }
10833
- // + separate addArrayItem button with arrayKey
11077
+ // + separate add-array-item button with arrayKey
10834
11078
  \`\`\``,
10835
11079
  explained: `# Array Fields - Complete Explanation
10836
11080
 
@@ -10902,7 +11146,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10902
11146
  // ADD button - place OUTSIDE the array
10903
11147
  {
10904
11148
  key: 'addContact',
10905
- type: 'addArrayItem',
11149
+ type: 'add-array-item',
10906
11150
  label: 'Add Contact',
10907
11151
  arrayKey: 'contacts', // \u26A0\uFE0F AT FIELD LEVEL!
10908
11152
  }
@@ -10914,7 +11158,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10914
11158
  fields: [
10915
11159
  [
10916
11160
  { key: 'name', type: 'input', label: 'Name' },
10917
- { key: 'remove', type: 'removeArrayItem', label: 'Remove' }
11161
+ { key: 'remove', type: 'remove-array-item', label: 'Remove' }
10918
11162
  ]
10919
11163
  ]
10920
11164
  }
@@ -10948,8 +11192,8 @@ expression: '(formValue.items || []).reduce((sum, item) => sum + (item.price ||
10948
11192
 
10949
11193
  \u274C Putting \`arrayKey\` in props (full API):
10950
11194
  \`\`\`typescript
10951
- { type: 'addArrayItem', props: { arrayKey: 'x' } } // WRONG
10952
- { type: 'addArrayItem', arrayKey: 'x' } // CORRECT
11195
+ { type: 'add-array-item', props: { arrayKey: 'x' } } // WRONG
11196
+ { type: 'add-array-item', arrayKey: 'x' } // CORRECT
10953
11197
  \`\`\``
10954
11198
  },
10955
11199
  "minimal-simplified-array": {