@ng-forge/dynamic-form-mcp 1.0.0-rc.4 → 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",
@@ -3007,7 +3078,7 @@ All features are exported from \`@ng-forge/dynamic-forms\`.
3007
3078
 
3008
3079
  ## CRITICAL: UI Library Differences
3009
3080
 
3010
- 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.
3011
3082
 
3012
3083
  ### Property Differences by Library
3013
3084
 
@@ -3050,24 +3121,24 @@ Container fields (\`page\`, \`group\`, \`row\`) do NOT support these properties:
3050
3121
  { key: 'volume', type: 'slider', label: 'Volume', min: 0, max: 100 }
3051
3122
  \`\`\`
3052
3123
 
3053
- 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.
3054
3125
 
3055
3126
  ## Validation Before Use
3056
3127
 
3057
- 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.
3058
3129
 
3059
3130
  \`\`\`typescript
3060
3131
  // Always specify the UI integration you're using
3061
- ngforge_validate_form_config({
3132
+ ngforge_validate({
3062
3133
  uiIntegration: 'material', // or 'bootstrap', 'primeng', 'ionic'
3063
3134
  config: { fields: [...] }
3064
3135
  })
3065
3136
  \`\`\`
3066
3137
 
3067
- 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"\`:
3068
3139
 
3069
3140
  \`\`\`typescript
3070
- ngforge_get_field_schema({ uiIntegration: 'material' })
3141
+ ngforge_lookup({ topic: 'input', depth: 'schema', uiIntegration: 'material' })
3071
3142
  \`\`\`
3072
3143
  `;
3073
3144
 
@@ -5180,7 +5251,7 @@ var MatPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5180
5251
  props: MatButtonPropsSchema.optional()
5181
5252
  });
5182
5253
  var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5183
- type: z33.literal("addArrayItem"),
5254
+ type: z33.literal("add-array-item"),
5184
5255
  /**
5185
5256
  * Key of the array field to add items to.
5186
5257
  * If omitted, uses the parent array context.
@@ -5189,7 +5260,7 @@ var MatAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5189
5260
  props: MatButtonPropsSchema.optional()
5190
5261
  });
5191
5262
  var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5192
- type: z33.literal("removeArrayItem"),
5263
+ type: z33.literal("remove-array-item"),
5193
5264
  /**
5194
5265
  * Key of the array field to remove items from.
5195
5266
  * If omitted, uses the parent array context.
@@ -5197,6 +5268,44 @@ var MatRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5197
5268
  arrayKey: z33.string().optional(),
5198
5269
  props: MatButtonPropsSchema.optional()
5199
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
+ });
5200
5309
 
5201
5310
  // internal/dynamic-forms-zod/material/src/mat-leaf-field.schema.ts
5202
5311
  import { z as z36 } from "zod";
@@ -5272,7 +5381,11 @@ var MatLeafFieldSchema = z36.discriminatedUnion("type", [
5272
5381
  MatNextButtonFieldSchema,
5273
5382
  MatPreviousButtonFieldSchema,
5274
5383
  MatAddArrayItemButtonFieldSchema,
5275
- MatRemoveArrayItemButtonFieldSchema
5384
+ MatRemoveArrayItemButtonFieldSchema,
5385
+ MatPrependArrayItemButtonFieldSchema,
5386
+ MatInsertArrayItemButtonFieldSchema,
5387
+ MatPopArrayItemButtonFieldSchema,
5388
+ MatShiftArrayItemButtonFieldSchema
5276
5389
  ]).superRefine(nullableValueRefine);
5277
5390
 
5278
5391
  // internal/dynamic-forms-zod/src/lib/schemas/containers/factories.ts
@@ -5740,13 +5853,34 @@ var BsPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5740
5853
  props: BsButtonPropsSchema.optional()
5741
5854
  });
5742
5855
  var BsAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5743
- type: z44.literal("addArrayItem"),
5856
+ type: z44.literal("add-array-item"),
5744
5857
  arrayKey: z44.string().optional(),
5745
5858
  props: BsButtonPropsSchema.optional()
5746
5859
  });
5747
5860
  var BsRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5748
- type: z44.literal("removeArrayItem"),
5861
+ type: z44.literal("remove-array-item"),
5862
+ arrayKey: z44.string().optional(),
5863
+ props: BsButtonPropsSchema.optional()
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"),
5749
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(),
5750
5884
  props: BsButtonPropsSchema.optional()
5751
5885
  });
5752
5886
 
@@ -5769,7 +5903,11 @@ var BsLeafFieldSchema = z45.discriminatedUnion("type", [
5769
5903
  BsNextButtonFieldSchema,
5770
5904
  BsPreviousButtonFieldSchema,
5771
5905
  BsAddArrayItemButtonFieldSchema,
5772
- BsRemoveArrayItemButtonFieldSchema
5906
+ BsRemoveArrayItemButtonFieldSchema,
5907
+ BsPrependArrayItemButtonFieldSchema,
5908
+ BsInsertArrayItemButtonFieldSchema,
5909
+ BsPopArrayItemButtonFieldSchema,
5910
+ BsShiftArrayItemButtonFieldSchema
5773
5911
  ]).superRefine(nullableValueRefine);
5774
5912
 
5775
5913
  // internal/dynamic-forms-zod/bootstrap/src/bs-form-config.schema.ts
@@ -5952,15 +6090,36 @@ var PrimePreviousButtonFieldSchema = BaseFieldDefSchema.extend({
5952
6090
  props: PrimeButtonPropsSchema.optional()
5953
6091
  });
5954
6092
  var PrimeAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5955
- type: z48.literal("addArrayItem"),
6093
+ type: z48.literal("add-array-item"),
5956
6094
  arrayKey: z48.string().optional(),
5957
6095
  props: PrimeButtonPropsSchema.optional()
5958
6096
  });
5959
6097
  var PrimeRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
5960
- type: z48.literal("removeArrayItem"),
6098
+ type: z48.literal("remove-array-item"),
5961
6099
  arrayKey: z48.string().optional(),
5962
6100
  props: PrimeButtonPropsSchema.optional()
5963
6101
  });
6102
+ var PrimePrependArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6103
+ type: z48.literal("prepend-array-item"),
6104
+ arrayKey: z48.string().optional(),
6105
+ props: PrimeButtonPropsSchema.optional()
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
+ });
5964
6123
 
5965
6124
  // internal/dynamic-forms-zod/primeng/src/prime-leaf-field.schema.ts
5966
6125
  import { z as z49 } from "zod";
@@ -5981,7 +6140,11 @@ var PrimeLeafFieldSchema = z49.discriminatedUnion("type", [
5981
6140
  PrimeNextButtonFieldSchema,
5982
6141
  PrimePreviousButtonFieldSchema,
5983
6142
  PrimeAddArrayItemButtonFieldSchema,
5984
- PrimeRemoveArrayItemButtonFieldSchema
6143
+ PrimeRemoveArrayItemButtonFieldSchema,
6144
+ PrimePrependArrayItemButtonFieldSchema,
6145
+ PrimeInsertArrayItemButtonFieldSchema,
6146
+ PrimePopArrayItemButtonFieldSchema,
6147
+ PrimeShiftArrayItemButtonFieldSchema
5985
6148
  ]).superRefine(nullableValueRefine);
5986
6149
 
5987
6150
  // internal/dynamic-forms-zod/primeng/src/prime-form-config.schema.ts
@@ -6206,15 +6369,36 @@ var IonicPreviousButtonFieldSchema = BaseFieldDefSchema.extend({
6206
6369
  props: IonicButtonPropsSchema.optional()
6207
6370
  });
6208
6371
  var IonicAddArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6209
- type: z52.literal("addArrayItem"),
6372
+ type: z52.literal("add-array-item"),
6210
6373
  arrayKey: z52.string().optional(),
6211
6374
  props: IonicButtonPropsSchema.optional()
6212
6375
  });
6213
6376
  var IonicRemoveArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6214
- 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"),
6215
6383
  arrayKey: z52.string().optional(),
6216
6384
  props: IonicButtonPropsSchema.optional()
6217
6385
  });
6386
+ var IonicInsertArrayItemButtonFieldSchema = BaseFieldDefSchema.extend({
6387
+ type: z52.literal("insert-array-item"),
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(),
6400
+ props: IonicButtonPropsSchema.optional()
6401
+ });
6218
6402
 
6219
6403
  // internal/dynamic-forms-zod/ionic/src/ionic-leaf-field.schema.ts
6220
6404
  import { z as z53 } from "zod";
@@ -6235,7 +6419,11 @@ var IonicLeafFieldSchema = z53.discriminatedUnion("type", [
6235
6419
  IonicNextButtonFieldSchema,
6236
6420
  IonicPreviousButtonFieldSchema,
6237
6421
  IonicAddArrayItemButtonFieldSchema,
6238
- IonicRemoveArrayItemButtonFieldSchema
6422
+ IonicRemoveArrayItemButtonFieldSchema,
6423
+ IonicPrependArrayItemButtonFieldSchema,
6424
+ IonicInsertArrayItemButtonFieldSchema,
6425
+ IonicPopArrayItemButtonFieldSchema,
6426
+ IonicShiftArrayItemButtonFieldSchema
6239
6427
  ]).superRefine(nullableValueRefine);
6240
6428
 
6241
6429
  // internal/dynamic-forms-zod/ionic/src/ionic-form-config.schema.ts
@@ -6580,8 +6768,12 @@ var NESTING_RULES = {
6580
6768
  "submit",
6581
6769
  "next",
6582
6770
  "previous",
6583
- "addArrayItem",
6584
- "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"
6585
6777
  ],
6586
6778
  forbidden: ["page"],
6587
6779
  message: "Pages cannot be nested inside other containers. ALL top-level fields must be pages if using multi-page mode."
@@ -6604,8 +6796,12 @@ var NESTING_RULES = {
6604
6796
  "submit",
6605
6797
  "next",
6606
6798
  "previous",
6607
- "addArrayItem",
6608
- "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"
6609
6805
  ],
6610
6806
  forbidden: ["page", "row", "hidden"],
6611
6807
  message: "Rows cannot contain pages, other rows, or hidden fields. Hidden fields should be at page or form level."
@@ -6628,8 +6824,12 @@ var NESTING_RULES = {
6628
6824
  "submit",
6629
6825
  "next",
6630
6826
  "previous",
6631
- "addArrayItem",
6632
- "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"
6633
6833
  ],
6634
6834
  forbidden: ["page", "group"],
6635
6835
  message: "Groups cannot contain pages or other groups (no nested groups)."
@@ -6653,8 +6853,12 @@ var NESTING_RULES = {
6653
6853
  "submit",
6654
6854
  "next",
6655
6855
  "previous",
6656
- "addArrayItem",
6657
- "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"
6658
6862
  ],
6659
6863
  forbidden: ["page", "array"],
6660
6864
  message: "Arrays cannot contain pages or other arrays (no nested arrays)."
@@ -6900,6 +7104,27 @@ function preValidateConfig(config) {
6900
7104
  });
6901
7105
  return errors;
6902
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
+ }
6903
7128
  function validateFormConfig(uiIntegration, config) {
6904
7129
  const schema = formConfigSchemas[uiIntegration];
6905
7130
  if (!schema) {
@@ -6914,15 +7139,16 @@ function validateFormConfig(uiIntegration, config) {
6914
7139
  errorSummary: `Unknown UI integration: ${uiIntegration}`
6915
7140
  };
6916
7141
  }
6917
- const preErrors = preValidateConfig(config);
6918
- const result = schema.safeParse(config);
7142
+ const normalizedConfig = normalizeLegacyArrayActionTypes(config);
7143
+ const preErrors = preValidateConfig(normalizedConfig);
7144
+ const result = schema.safeParse(normalizedConfig);
6919
7145
  if (result.success && preErrors.length === 0) {
6920
7146
  return {
6921
7147
  valid: true,
6922
7148
  data: result.data
6923
7149
  };
6924
7150
  }
6925
- const zodErrors = result.success ? [] : formatZodError(result.error, config);
7151
+ const zodErrors = result.success ? [] : formatZodError(result.error, normalizedConfig);
6926
7152
  const allErrors = [...preErrors, ...zodErrors];
6927
7153
  return {
6928
7154
  valid: false,
@@ -6949,29 +7175,32 @@ ${UI_INTEGRATIONS.map((ui) => `- ${ui}`).join("\n")}
6949
7175
  ## Field Types
6950
7176
  ${fieldTypes.map((ft) => `- ${ft}`).join("\n")}
6951
7177
 
6952
- ## Tools (4 total - consolidated)
7178
+ ## Tools (5 total - consolidated)
6953
7179
 
6954
- **1. START HERE - One-shot reference:**
6955
- \`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
6956
7183
  - Property placement rules, condition syntax, copy-paste patterns, common errors
6957
- - Component API (template binding, event names)
6958
- - **Use this first** - it has 90% of what you need in one call
7184
+ - depth="brief|full|schema" (default full); uiIntegration filters schema output
6959
7185
 
6960
- **2. Validation:**
6961
- \`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?)\`
6962
7193
  - Validates config against actual TypeScript types
6963
7194
  - Catches errors before runtime
6964
7195
 
6965
- **3. Field info + schema:**
6966
- \`ngforge_get_field_info(fieldType?, uiIntegration?, includeSchema?)\`
6967
- - Properties, validators, and examples for a specific field type
6968
- - Set includeSchema=true for JSON Schema (machine-readable)
6969
-
6970
- **4. Examples + deep explanations:**
6971
- \`ngforge_get_example(pattern?, depth?)\`
7196
+ **4. Examples:**
7197
+ \`ngforge_examples(pattern, depth?)\`
6972
7198
  - Patterns: complete, derivation, conditional, multi-page, validation
6973
- - depth="example" (default) = working code
6974
- - 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
6975
7204
  `
6976
7205
  }
6977
7206
  ]
@@ -7631,8 +7860,8 @@ interface SimplifiedArrayField {
7631
7860
 
7632
7861
  The simplified API is normalized into the full API at runtime:
7633
7862
  1. Each \`value\` element creates an item using the \`template\` structure
7634
- 2. An \`addArrayItem\` button is auto-generated after the array (unless \`addButton: false\`)
7635
- 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\`)
7636
7865
 
7637
7866
  ## Conditional Visibility
7638
7867
 
@@ -9387,19 +9616,19 @@ const config = { fields: [...] } as const satisfies FormConfig;
9387
9616
  - Together they give you: type safety + exact type inference`
9388
9617
  },
9389
9618
  "array-buttons": {
9390
- brief: `**Add:** \`{ type: 'addArrayItem', key: 'add', label: 'Add', arrayKey: 'contacts' }\`
9391
- **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)
9392
9621
  \u26A0\uFE0F arrayKey at FIELD level, NOT in props!`,
9393
9622
  full: `# Array Buttons (Add/Remove Items)
9394
9623
 
9395
- **UI libraries provide \`addArrayItem\` and \`removeArrayItem\` button types.**
9624
+ **UI libraries provide \`add-array-item\` and \`remove-array-item\` button types.**
9396
9625
 
9397
9626
  ## Add Item Button
9398
9627
 
9399
9628
  \`\`\`typescript
9400
9629
  {
9401
9630
  key: 'addPhone',
9402
- type: 'addArrayItem',
9631
+ type: 'add-array-item',
9403
9632
  label: 'Add Phone',
9404
9633
  arrayKey: 'phones', // \u26A0\uFE0F AT FIELD LEVEL, NOT IN PROPS!
9405
9634
  props: {
@@ -9421,7 +9650,7 @@ const config = { fields: [...] } as const satisfies FormConfig;
9421
9650
  { key: 'number', type: 'input', label: 'Phone Number' },
9422
9651
  {
9423
9652
  key: 'removePhone',
9424
- type: 'removeArrayItem',
9653
+ type: 'remove-array-item',
9425
9654
  label: 'Remove',
9426
9655
  // arrayKey not needed - inferred from parent array
9427
9656
  props: { color: 'warn' }
@@ -9436,13 +9665,13 @@ const config = { fields: [...] } as const satisfies FormConfig;
9436
9665
  \`\`\`typescript
9437
9666
  // WRONG - arrayKey in props
9438
9667
  {
9439
- type: 'addArrayItem',
9668
+ type: 'add-array-item',
9440
9669
  props: { arrayKey: 'phones' } // \u274C WRONG LOCATION
9441
9670
  }
9442
9671
 
9443
9672
  // CORRECT - arrayKey at field level
9444
9673
  {
9445
- type: 'addArrayItem',
9674
+ type: 'add-array-item',
9446
9675
  arrayKey: 'phones', // \u2705 CORRECT
9447
9676
  props: { color: 'primary' }
9448
9677
  }
@@ -9711,8 +9940,19 @@ var TOPIC_ALIASES = {
9711
9940
  valueof: "context-api",
9712
9941
  "add-array": "array-buttons",
9713
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",
9714
9950
  addarrayitem: "array-buttons",
9951
+ prependarrayitem: "array-buttons",
9952
+ insertarrayitem: "array-buttons",
9715
9953
  removearrayitem: "array-buttons",
9954
+ poparrayitem: "array-buttons",
9955
+ shiftarrayitem: "array-buttons",
9716
9956
  "custom-validator": "custom-validators",
9717
9957
  customvalidator: "custom-validators",
9718
9958
  mistakes: "pitfalls",
@@ -10757,7 +10997,7 @@ For full control, use the \`fields\`-based API with explicit add/remove buttons:
10757
10997
  ]
10758
10998
  ]
10759
10999
  }
10760
- // + separate addArrayItem button with arrayKey
11000
+ // + separate add-array-item button with arrayKey
10761
11001
  \`\`\``,
10762
11002
  explained: `# Array Fields - Complete Explanation
10763
11003
 
@@ -10829,7 +11069,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10829
11069
  // ADD button - place OUTSIDE the array
10830
11070
  {
10831
11071
  key: 'addContact',
10832
- type: 'addArrayItem',
11072
+ type: 'add-array-item',
10833
11073
  label: 'Add Contact',
10834
11074
  arrayKey: 'contacts', // \u26A0\uFE0F AT FIELD LEVEL!
10835
11075
  }
@@ -10841,7 +11081,7 @@ For full control, use \`fields\` with explicit item definitions and manual add/r
10841
11081
  fields: [
10842
11082
  [
10843
11083
  { key: 'name', type: 'input', label: 'Name' },
10844
- { key: 'remove', type: 'removeArrayItem', label: 'Remove' }
11084
+ { key: 'remove', type: 'remove-array-item', label: 'Remove' }
10845
11085
  ]
10846
11086
  ]
10847
11087
  }
@@ -10875,8 +11115,8 @@ expression: '(formValue.items || []).reduce((sum, item) => sum + (item.price ||
10875
11115
 
10876
11116
  \u274C Putting \`arrayKey\` in props (full API):
10877
11117
  \`\`\`typescript
10878
- { type: 'addArrayItem', props: { arrayKey: 'x' } } // WRONG
10879
- { type: 'addArrayItem', arrayKey: 'x' } // CORRECT
11118
+ { type: 'add-array-item', props: { arrayKey: 'x' } } // WRONG
11119
+ { type: 'add-array-item', arrayKey: 'x' } // CORRECT
10880
11120
  \`\`\``
10881
11121
  },
10882
11122
  "minimal-simplified-array": {