@ng-forge/dynamic-form-mcp 1.2.0-next.8 → 1.2.0-next.9

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.
@@ -24,7 +24,7 @@ var FIELD_TYPES = [
24
24
  },
25
25
  validationSupported: true,
26
26
  source: "adapter",
27
- allowedIn: ["top-level", "page", "row", "group", "array"],
27
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
28
28
  example: `{
29
29
  key: 'email',
30
30
  type: 'input',
@@ -59,7 +59,7 @@ var FIELD_TYPES = [
59
59
  },
60
60
  validationSupported: true,
61
61
  source: "adapter",
62
- allowedIn: ["top-level", "page", "row", "group", "array"],
62
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
63
63
  example: `{
64
64
  key: 'description',
65
65
  type: 'textarea',
@@ -93,7 +93,7 @@ var FIELD_TYPES = [
93
93
  },
94
94
  validationSupported: true,
95
95
  source: "adapter",
96
- allowedIn: ["top-level", "page", "row", "group", "array"],
96
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
97
97
  example: `{
98
98
  key: 'country',
99
99
  type: 'select',
@@ -115,7 +115,7 @@ var FIELD_TYPES = [
115
115
  props: {},
116
116
  validationSupported: true,
117
117
  source: "adapter",
118
- allowedIn: ["top-level", "page", "row", "group", "array"],
118
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
119
119
  example: `{
120
120
  key: 'acceptTerms',
121
121
  type: 'checkbox',
@@ -140,7 +140,7 @@ var FIELD_TYPES = [
140
140
  },
141
141
  validationSupported: true,
142
142
  source: "adapter",
143
- allowedIn: ["top-level", "page", "row", "group", "array"],
143
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
144
144
  example: `{
145
145
  key: 'interests',
146
146
  type: 'multi-checkbox',
@@ -170,7 +170,7 @@ var FIELD_TYPES = [
170
170
  },
171
171
  validationSupported: true,
172
172
  source: "adapter",
173
- allowedIn: ["top-level", "page", "row", "group", "array"],
173
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
174
174
  example: `{
175
175
  key: 'gender',
176
176
  type: 'radio',
@@ -205,7 +205,7 @@ var FIELD_TYPES = [
205
205
  },
206
206
  validationSupported: true,
207
207
  source: "adapter",
208
- allowedIn: ["top-level", "page", "row", "group", "array"],
208
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
209
209
  example: `{
210
210
  key: 'birthDate',
211
211
  type: 'datepicker',
@@ -224,7 +224,7 @@ var FIELD_TYPES = [
224
224
  props: {},
225
225
  validationSupported: true,
226
226
  source: "adapter",
227
- allowedIn: ["top-level", "page", "row", "group", "array"],
227
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
228
228
  example: `{
229
229
  key: 'notifications',
230
230
  type: 'toggle',
@@ -263,7 +263,7 @@ var FIELD_TYPES = [
263
263
  },
264
264
  validationSupported: true,
265
265
  source: "adapter",
266
- allowedIn: ["top-level", "page", "row", "group", "array"],
266
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
267
267
  example: `{
268
268
  key: 'volume',
269
269
  type: 'slider',
@@ -284,7 +284,7 @@ var FIELD_TYPES = [
284
284
  props: {},
285
285
  validationSupported: false,
286
286
  source: "core",
287
- allowedIn: ["top-level (single-page forms only)", "page.fields", "group.fields", "array.fields"],
287
+ allowedIn: ["top-level (single-page forms only)", "page.fields", "group.fields", "array.fields", "container"],
288
288
  notAllowedIn: ["row", "top-level when using pages"],
289
289
  example: `// Hidden field - value is REQUIRED!
290
290
  {
@@ -321,7 +321,7 @@ var FIELD_TYPES = [
321
321
  },
322
322
  validationSupported: false,
323
323
  source: "core",
324
- allowedIn: ["top-level", "page", "row", "group", "array"],
324
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
325
325
  example: `{
326
326
  key: 'sectionTitle',
327
327
  type: 'text',
@@ -424,11 +424,12 @@ var FIELD_TYPES = [
424
424
  },
425
425
  validationSupported: true,
426
426
  source: "core",
427
- allowedIn: ["top-level", "page", "row", "array"],
427
+ allowedIn: ["top-level", "page", "row", "array", "container"],
428
428
  notAllowedIn: ["group"],
429
429
  canContain: [
430
430
  "row",
431
431
  "array",
432
+ "container",
432
433
  "input",
433
434
  "textarea",
434
435
  "select",
@@ -522,11 +523,12 @@ var FIELD_TYPES = [
522
523
  },
523
524
  validationSupported: true,
524
525
  source: "core",
525
- allowedIn: ["top-level", "page", "row", "group"],
526
+ allowedIn: ["top-level", "page", "row", "group", "container"],
526
527
  notAllowedIn: ["array"],
527
528
  canContain: [
528
529
  "row",
529
530
  "group",
531
+ "container",
530
532
  "input",
531
533
  "textarea",
532
534
  "select",
@@ -588,6 +590,74 @@ var FIELD_TYPES = [
588
590
  // ? { kind: 'periodOrder' } : null`,
589
591
  minimalExample: `{ key: 'items', type: 'array', fields: [...] }`
590
592
  },
593
+ {
594
+ type: "container",
595
+ category: "container",
596
+ description: "Wraps its children in UI chrome via a chain of wrapper components. Containers do NOT have a label property and do NOT create a nesting level in form values \u2014 child values are flattened into the parent, exactly like rows. The 'wrappers' property is REQUIRED (use [] for no chrome). A container is NOT a group with chrome and the two are not substitutable: a container flattens child values into the parent (like a row), while a group nests them under its own key and owns a schema path, so swapping one for the other changes the submitted value shape and which validators can run. Wrappers are applied outermost-first, so the first entry in the array is the outermost element. Supports only 'hidden' logic type for conditional visibility. Like `row` and `page`, a container flattens into its parent and has no schema path of its own, so it does NOT support container-level `validators`, `required` or `validationMessages` \u2014 use `group` or `array` for cross-field rules.",
597
+ valueType: void 0,
598
+ baseInterface: "FieldDef",
599
+ props: {
600
+ fields: {
601
+ name: "fields",
602
+ type: "ContainerAllowedChildren[]",
603
+ description: "Child fields to render inside the wrapper chain. Allowed: rows, groups, arrays, nested containers, hidden fields, and value fields (input, select, etc). NOT ALLOWED: pages",
604
+ required: true
605
+ },
606
+ wrappers: {
607
+ name: "wrappers",
608
+ type: "WrapperConfig[]",
609
+ description: "REQUIRED. Wrapper components chained around the children, outermost first. Use [] for no chrome. Each entry needs a 'type'; the built-in wrapper is 'css', which takes 'cssClasses'. Custom wrapper types can be registered.",
610
+ required: true
611
+ }
612
+ },
613
+ validationSupported: false,
614
+ source: "core",
615
+ allowedIn: ["top-level", "page", "group", "array", "row", "container"],
616
+ notAllowedIn: [],
617
+ canContain: [
618
+ "row",
619
+ "group",
620
+ "array",
621
+ "container",
622
+ "hidden",
623
+ "input",
624
+ "textarea",
625
+ "select",
626
+ "checkbox",
627
+ "multi-checkbox",
628
+ "radio",
629
+ "datepicker",
630
+ "toggle",
631
+ "slider",
632
+ "text",
633
+ "button",
634
+ "submit",
635
+ "next",
636
+ "previous",
637
+ "add-array-item",
638
+ "prepend-array-item",
639
+ "insert-array-item",
640
+ "remove-array-item",
641
+ "pop-array-item",
642
+ "shift-array-item"
643
+ ],
644
+ cannotContain: ["page"],
645
+ example: `{
646
+ key: 'billingChrome',
647
+ type: 'container',
648
+ // NOTE: Containers do NOT have a label property
649
+ // wrappers is REQUIRED \u2014 use [] when no chrome is needed
650
+ wrappers: [{ type: 'css', cssClasses: 'card p-3' }],
651
+ fields: [
652
+ { key: 'street', type: 'input', label: 'Street' },
653
+ { key: 'city', type: 'input', label: 'City' }
654
+ ]
655
+ }
656
+ // Values flatten: { street: '', city: '' } \u2014 no 'billingChrome' key
657
+ // NOT ALLOWED in containers:
658
+ // - type: 'page' (pages are top-level only)`,
659
+ minimalExample: `{ key: 'chrome', type: 'container', wrappers: [], fields: [...] }`
660
+ },
591
661
  {
592
662
  type: "page",
593
663
  category: "container",
@@ -605,11 +675,12 @@ var FIELD_TYPES = [
605
675
  validationSupported: false,
606
676
  source: "core",
607
677
  allowedIn: ["top-level"],
608
- notAllowedIn: ["page", "row", "group", "array"],
678
+ notAllowedIn: ["page", "row", "group", "array", "container"],
609
679
  canContain: [
610
680
  "row",
611
681
  "group",
612
682
  "array",
683
+ "container",
613
684
  "input",
614
685
  "textarea",
615
686
  "select",
@@ -649,7 +720,7 @@ var FIELD_TYPES = [
649
720
  props: {},
650
721
  validationSupported: false,
651
722
  source: "adapter",
652
- allowedIn: ["top-level", "page", "row", "group", "array"],
723
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
653
724
  example: `{
654
725
  key: 'next',
655
726
  type: 'next',
@@ -666,7 +737,7 @@ var FIELD_TYPES = [
666
737
  props: {},
667
738
  validationSupported: false,
668
739
  source: "adapter",
669
- allowedIn: ["top-level", "page", "row", "group", "array"],
740
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
670
741
  example: `{
671
742
  key: 'back',
672
743
  type: 'previous',
@@ -690,7 +761,7 @@ var FIELD_TYPES = [
690
761
  },
691
762
  validationSupported: false,
692
763
  source: "adapter",
693
- allowedIn: ["top-level", "page", "row", "group", "array"],
764
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
694
765
  example: `// RECOMMENDED: Use pre-defined button types for common actions
695
766
  { key: 'submit', type: 'submit', label: 'Submit Form' }
696
767
  { key: 'next', type: 'next', label: 'Next' }
@@ -717,7 +788,7 @@ var FIELD_TYPES = [
717
788
  props: {},
718
789
  validationSupported: false,
719
790
  source: "adapter",
720
- allowedIn: ["top-level", "page", "row", "group", "array"],
791
+ allowedIn: ["top-level", "page", "row", "group", "array", "container"],
721
792
  example: `{
722
793
  key: 'submit',
723
794
  type: 'submit',
@@ -734,7 +805,7 @@ var FIELD_TYPES = [
734
805
  props: {},
735
806
  validationSupported: false,
736
807
  source: "adapter",
737
- allowedIn: ["array", "row", "group"],
808
+ allowedIn: ["array", "row", "group", "container"],
738
809
  example: `{
739
810
  key: 'addContact',
740
811
  type: 'add-array-item',
@@ -751,7 +822,7 @@ var FIELD_TYPES = [
751
822
  props: {},
752
823
  validationSupported: false,
753
824
  source: "adapter",
754
- allowedIn: ["array", "row", "group"],
825
+ allowedIn: ["array", "row", "group", "container"],
755
826
  example: `{
756
827
  key: 'prependContact',
757
828
  type: 'prepend-array-item',
@@ -768,7 +839,7 @@ var FIELD_TYPES = [
768
839
  props: {},
769
840
  validationSupported: false,
770
841
  source: "adapter",
771
- allowedIn: ["array", "row", "group"],
842
+ allowedIn: ["array", "row", "group", "container"],
772
843
  example: `{
773
844
  key: 'insertContact',
774
845
  type: 'insert-array-item',
@@ -786,7 +857,7 @@ var FIELD_TYPES = [
786
857
  props: {},
787
858
  validationSupported: false,
788
859
  source: "adapter",
789
- allowedIn: ["array", "row", "group"],
860
+ allowedIn: ["array", "row", "group", "container"],
790
861
  example: `{
791
862
  key: 'removeContact',
792
863
  type: 'remove-array-item',
@@ -803,7 +874,7 @@ var FIELD_TYPES = [
803
874
  props: {},
804
875
  validationSupported: false,
805
876
  source: "adapter",
806
- allowedIn: ["array", "row", "group"],
877
+ allowedIn: ["array", "row", "group", "container"],
807
878
  example: `{
808
879
  key: 'popContact',
809
880
  type: 'pop-array-item',
@@ -821,7 +892,7 @@ var FIELD_TYPES = [
821
892
  props: {},
822
893
  validationSupported: false,
823
894
  source: "adapter",
824
- allowedIn: ["array", "row", "group"],
895
+ allowedIn: ["array", "row", "group", "container"],
825
896
  example: `{
826
897
  key: 'shiftContact',
827
898
  type: 'shift-array-item',
@@ -4811,15 +4882,23 @@ var ContainerLogicSchema = z13.object({
4811
4882
  type: z13.literal("hidden"),
4812
4883
  condition: z13.union([ConditionalExpressionSchema, z13.boolean()])
4813
4884
  });
4885
+ var SIMPLIFIED_ONLY_PROPS = ["template", "value", "addButton", "removeButton"];
4886
+ var SIMPLIFIED_ONLY_HINTS = {
4887
+ template: 'Use "fields" for the full API, or "template" for the simplified one.',
4888
+ value: 'Set initial values on the field definitions inside "fields".',
4889
+ addButton: 'Add an "add-array-item" or "insert-array-item" button as a field.',
4890
+ removeButton: 'Add a "remove-array-item" button to the item definition.'
4891
+ };
4814
4892
  function createContainerSchemas(options) {
4815
4893
  const { leafFieldSchema } = options;
4816
4894
  const AnyFieldSchema = z13.lazy(
4817
- () => z13.union([
4895
+ () => z13.discriminatedUnion("type", [
4818
4896
  leafFieldSchema,
4819
4897
  PageFieldSchema,
4820
4898
  RowFieldSchema,
4821
4899
  GroupFieldSchema,
4822
- ArrayFieldSchema
4900
+ ArrayFieldSchema,
4901
+ ContainerFieldSchema
4823
4902
  ])
4824
4903
  );
4825
4904
  const ContainerBaseSchema = BaseFieldDefSchema.omit({
@@ -4831,6 +4910,18 @@ function createContainerSchemas(options) {
4831
4910
  label: z13.never().optional(),
4832
4911
  meta: z13.never().optional()
4833
4912
  });
4913
+ const ContainerValidationShape = {
4914
+ required: z13.boolean().optional(),
4915
+ validators: ValidatorsArraySchema.optional(),
4916
+ validationMessages: ValidationMessagesSchema.optional()
4917
+ };
4918
+ const WrapperConfigSchema = z13.object({ type: z13.string() }).passthrough();
4919
+ const ContainerFieldSchema = ContainerBaseSchema.extend({
4920
+ type: z13.literal("container"),
4921
+ fields: z13.array(AnyFieldSchema),
4922
+ wrappers: z13.array(WrapperConfigSchema),
4923
+ logic: z13.array(ContainerLogicSchema).optional()
4924
+ });
4834
4925
  const PageFieldSchema = ContainerBaseSchema.extend({
4835
4926
  type: z13.literal("page"),
4836
4927
  fields: z13.array(AnyFieldSchema),
@@ -4847,33 +4938,27 @@ function createContainerSchemas(options) {
4847
4938
  const GroupFieldSchema = ContainerBaseSchema.extend({
4848
4939
  type: z13.literal("group"),
4849
4940
  fields: z13.array(AnyFieldSchema),
4941
+ ...ContainerValidationShape,
4850
4942
  // Container logic - only 'hidden' type allowed (same as pages)
4851
4943
  logic: z13.array(ContainerLogicSchema).optional()
4852
4944
  });
4853
4945
  const ArrayButtonConfigSchema = z13.object({
4854
4946
  label: z13.string().optional(),
4855
- props: z13.record(z13.unknown()).optional()
4856
- });
4857
- const FullArrayFieldSchema = ContainerBaseSchema.extend({
4858
- type: z13.literal("array"),
4859
- fields: z13.array(AnyFieldSchema),
4860
- logic: z13.array(ContainerLogicSchema).optional(),
4861
- // Full API does not use template
4862
- template: z13.never().optional(),
4863
- // Array length validation
4864
- minLength: z13.number().int().min(0).optional(),
4865
- maxLength: z13.number().int().min(0).optional()
4947
+ props: z13.record(z13.string(), z13.unknown()).optional()
4866
4948
  });
4867
4949
  const ArrayAllowedChildSchema = z13.lazy(
4868
4950
  () => AnyFieldSchema.refine((field) => field.type !== "page" && field.type !== "array", {
4869
4951
  message: "Array templates cannot contain page or array fields. Only leaf fields, rows, and groups are allowed."
4870
4952
  })
4871
4953
  );
4872
- const SimplifiedArrayFieldSchema = ContainerBaseSchema.extend({
4954
+ const ArrayFieldSchema = ContainerBaseSchema.extend({
4873
4955
  type: z13.literal("array"),
4874
- // Template: single field (primitive array) or array of fields (object array)
4956
+ ...ContainerValidationShape,
4957
+ // Full API: explicit item definitions.
4958
+ fields: z13.array(AnyFieldSchema).optional(),
4959
+ // Simplified API: single field (primitive array) or array of fields (object array).
4875
4960
  // Only ArrayAllowedChildren (leaf fields, rows, groups) are valid — no pages or nested arrays.
4876
- template: z13.union([ArrayAllowedChildSchema, z13.array(ArrayAllowedChildSchema)]),
4961
+ template: z13.union([ArrayAllowedChildSchema, z13.array(ArrayAllowedChildSchema)]).optional(),
4877
4962
  // Initial values for the array
4878
4963
  value: z13.array(z13.unknown()).optional(),
4879
4964
  // Button customization or opt-out (false to disable)
@@ -4883,18 +4968,64 @@ function createContainerSchemas(options) {
4883
4968
  // Array length validation
4884
4969
  minLength: z13.number().int().min(0).optional(),
4885
4970
  maxLength: z13.number().int().min(0).optional(),
4886
- // Simplified API does not use fields
4887
- fields: z13.never().optional(),
4971
+ // The array size properties are minLength/maxLength. These are the common
4972
+ // wrong spelling, and naming them keeps the mistake from being silently
4973
+ // stripped. Previously only the simplified API rejected them.
4888
4974
  minItems: z13.never().optional(),
4889
4975
  maxItems: z13.never().optional()
4976
+ }).superRefine((field, ctx) => {
4977
+ const hasFields = field.fields !== void 0;
4978
+ const hasTemplate = field.template !== void 0;
4979
+ if (hasFields && hasTemplate) {
4980
+ ctx.addIssue({
4981
+ code: "custom",
4982
+ message: 'Array has BOTH "fields" and "template". These are mutually exclusive: use "fields" for the full API, or "template" + "value" for the simplified API.'
4983
+ });
4984
+ return;
4985
+ }
4986
+ if (!hasFields && !hasTemplate) {
4987
+ ctx.addIssue({
4988
+ code: "custom",
4989
+ message: 'Array is MISSING both "fields" and "template". Use "fields" (full API) or "template" + "value" (simplified API).'
4990
+ });
4991
+ return;
4992
+ }
4993
+ if (hasFields) {
4994
+ for (const prop of SIMPLIFIED_ONLY_PROPS) {
4995
+ if (prop === "template" || field[prop] === void 0) continue;
4996
+ ctx.addIssue({
4997
+ code: "custom",
4998
+ path: [prop],
4999
+ message: `Array uses the full API ("fields"), so "${prop}" is not allowed: it belongs to the simplified API. ${SIMPLIFIED_ONLY_HINTS[prop]}`
5000
+ });
5001
+ }
5002
+ }
5003
+ }).meta({
5004
+ // The refinement above is invisible to JSON Schema generation, and the
5005
+ // generated schema is authoring guidance for a model. Two optional
5006
+ // properties with no stated relationship reads as "pass either, both or
5007
+ // neither", which is exactly the mistake the refinement rejects at
5008
+ // runtime. Restating the rule as `oneOf` keeps the published schema
5009
+ // saying what the validator enforces — the union of two array schemas
5010
+ // used to express this, and collapsing them to one schema lost it.
5011
+ description: 'Array field. Use EXACTLY ONE of "fields" (full API: explicit item definitions) or "template" (simplified API: one field, or an array of fields, repeated per item). Never both, never neither. "value", "addButton" and "removeButton" belong to the simplified API only: with "fields", put initial values on the item definitions and add buttons as fields.',
5012
+ oneOf: [
5013
+ {
5014
+ required: ["fields"],
5015
+ // `not` wraps an `anyOf`, not one multi-name `required`: the latter
5016
+ // would only forbid all of them being present at once.
5017
+ not: { anyOf: SIMPLIFIED_ONLY_PROPS.map((prop) => ({ required: [prop] })) }
5018
+ },
5019
+ { required: ["template"], not: { required: ["fields"] } }
5020
+ ]
4890
5021
  });
4891
- const ArrayFieldSchema = z13.union([FullArrayFieldSchema, SimplifiedArrayFieldSchema]);
4892
5022
  const AllFieldsSchema = AnyFieldSchema;
4893
5023
  return {
4894
5024
  PageFieldSchema,
4895
5025
  RowFieldSchema,
4896
5026
  GroupFieldSchema,
4897
5027
  ArrayFieldSchema,
5028
+ ContainerFieldSchema,
4898
5029
  AllFieldsSchema
4899
5030
  };
4900
5031
  }
@@ -5103,6 +5234,9 @@ var BaseFormConfigSchema = z18.object({
5103
5234
  defaultValidationMessages: ValidationMessagesSchema.optional()
5104
5235
  });
5105
5236
 
5237
+ // internal/dynamic-forms-validation/validate/src/json-schema/form-config-json-schema.ts
5238
+ import { z as z55 } from "zod";
5239
+
5106
5240
  // internal/dynamic-forms-validation/material/src/props/mat-common-props.schema.ts
5107
5241
  import { z as z19 } from "zod";
5108
5242
  var MatFormFieldAppearanceSchema = z19.enum(["fill", "outline"]);
@@ -6592,8 +6726,14 @@ var IonicFormDefaultPropsSchema = z54.object({
6592
6726
  });
6593
6727
  var IonicFormConfigSchema = createFormConfigSchema(IonicFieldSchema, IonicFormDefaultPropsSchema);
6594
6728
 
6729
+ // internal/dynamic-forms-validation/validate/src/json-schema/form-config-json-schema.ts
6730
+ function toJsonSchema(schema, name, basePath) {
6731
+ const jsonSchema = z55.toJSONSchema(schema, { target: "draft-7", io: "input", unrepresentable: "any" });
6732
+ jsonSchema["$id"] = basePath ? `${basePath.replace(/\/$/, "")}/${name}` : name;
6733
+ return jsonSchema;
6734
+ }
6735
+
6595
6736
  // internal/dynamic-forms-validation/validate/src/json-schema/field-type-json-schemas.ts
6596
- import zodToJsonSchema from "zod-to-json-schema";
6597
6737
  var fieldTypeSchemas = {
6598
6738
  material: {
6599
6739
  input: MatInputFieldSchema,
@@ -6682,41 +6822,34 @@ function getFieldTypeJsonSchema(uiIntegration, fieldType) {
6682
6822
  if (!schema) {
6683
6823
  throw new Error(`Unknown field type: ${fieldType}. Valid: ${getSupportedFieldTypes().join(", ")}`);
6684
6824
  }
6685
- const jsonSchema = zodToJsonSchema(schema, {
6686
- name: `${uiIntegration}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}Field`,
6687
- $refStrategy: "none",
6688
- errorMessages: true
6689
- });
6690
- return jsonSchema;
6825
+ return toJsonSchema(schema, `${uiIntegration}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}Field`);
6691
6826
  }
6692
6827
 
6693
6828
  // internal/dynamic-forms-validation/src/lib/schemas/field-type-names.ts
6694
- import { z as z55 } from "zod";
6829
+ import { z as z56 } from "zod";
6695
6830
  var MAX_DEPTH = 20;
6696
6831
  function collectDiscriminator(schema, into) {
6697
- if (schema instanceof z55.ZodLiteral) {
6698
- if (typeof schema.value === "string") into.add(schema.value);
6832
+ if (schema instanceof z56.ZodLiteral) {
6833
+ for (const value of schema.def.values) {
6834
+ if (typeof value === "string") into.add(value);
6835
+ }
6699
6836
  return;
6700
6837
  }
6701
- if (schema instanceof z55.ZodEnum) {
6838
+ if (schema instanceof z56.ZodEnum) {
6702
6839
  for (const value of schema.options) into.add(value);
6703
6840
  }
6704
6841
  }
6705
6842
  function visit(schema, into, depth) {
6706
6843
  if (depth > MAX_DEPTH) return;
6707
- if (schema instanceof z55.ZodLazy) {
6708
- visit(schema.schema, into, depth + 1);
6844
+ if (schema instanceof z56.ZodLazy) {
6845
+ visit(schema.unwrap(), into, depth + 1);
6709
6846
  return;
6710
6847
  }
6711
- if (schema instanceof z55.ZodEffects) {
6712
- visit(schema.innerType(), into, depth + 1);
6713
- return;
6714
- }
6715
- if (schema instanceof z55.ZodDiscriminatedUnion || schema instanceof z55.ZodUnion) {
6848
+ if (schema instanceof z56.ZodUnion) {
6716
6849
  for (const option of schema.options) visit(option, into, depth + 1);
6717
6850
  return;
6718
6851
  }
6719
- if (schema instanceof z55.ZodObject) {
6852
+ if (schema instanceof z56.ZodObject) {
6720
6853
  collectDiscriminator(schema.shape["type"], into);
6721
6854
  return;
6722
6855
  }
@@ -6789,14 +6922,14 @@ var DID_YOU_MEAN = {
6789
6922
  validation: "Did you mean to use validator shorthand (`required`, `email`, `min`, etc.) or `validators: [...]` array?"
6790
6923
  };
6791
6924
  function formatZodError(error, uiIntegration, config) {
6792
- const errors = error.errors.map((err) => {
6925
+ const errors = error.issues.map((err) => {
6793
6926
  const path = err.path.join(".") || "root";
6794
6927
  let message = err.message;
6795
6928
  let expected;
6796
6929
  let received;
6797
6930
  if ("expected" in err) expected = String(err.expected);
6798
6931
  if ("received" in err) received = String(err.received);
6799
- if (message === "Invalid input" || message === "Invalid union") {
6932
+ if (err.code === "invalid_union") {
6800
6933
  const fieldMatch = path.match(/fields\.(\d+)/);
6801
6934
  if (fieldMatch && config && typeof config === "object" && "fields" in config) {
6802
6935
  const fields = config.fields;
@@ -6927,123 +7060,31 @@ var FORBIDDEN_HIDDEN_PROPS = [
6927
7060
  "pattern",
6928
7061
  "placeholder"
6929
7062
  ];
6930
- var CONTAINER_FORBIDDEN_PROPS = ["validators", "required", "email", "min", "max", "minLength", "maxLength", "pattern", "value"];
7063
+ var CONTAINER_FORBIDDEN_PROPS = ["email", "min", "max", "pattern", "value"];
7064
+ var VALIDATING_CONTAINERS = ["group", "array"];
7065
+ var CONTAINER_VALIDATION_PROPS = ["validators", "required", "validationMessages"];
7066
+ var ARRAY_SIZE_PROPS = ["minLength", "maxLength"];
6931
7067
  var FIELDS_REQUIRING_OPTIONS = ["select", "radio", "multi-checkbox"];
6932
7068
  var NESTING_RULES = {
6933
7069
  page: {
6934
- allowed: [
6935
- "row",
6936
- "group",
6937
- "array",
6938
- "input",
6939
- "textarea",
6940
- "select",
6941
- "checkbox",
6942
- "multi-checkbox",
6943
- "radio",
6944
- "datepicker",
6945
- "toggle",
6946
- "slider",
6947
- "hidden",
6948
- "text",
6949
- "button",
6950
- "submit",
6951
- "next",
6952
- "previous",
6953
- "add-array-item",
6954
- "prepend-array-item",
6955
- "insert-array-item",
6956
- "remove-array-item",
6957
- "pop-array-item",
6958
- "shift-array-item"
6959
- ],
6960
7070
  forbidden: ["page"],
6961
7071
  message: "Pages cannot be nested inside other containers. ALL top-level fields must be pages if using multi-page mode."
6962
7072
  },
6963
7073
  row: {
6964
- allowed: [
6965
- "group",
6966
- "array",
6967
- "input",
6968
- "textarea",
6969
- "select",
6970
- "checkbox",
6971
- "multi-checkbox",
6972
- "radio",
6973
- "datepicker",
6974
- "toggle",
6975
- "slider",
6976
- "text",
6977
- "button",
6978
- "submit",
6979
- "next",
6980
- "previous",
6981
- "add-array-item",
6982
- "prepend-array-item",
6983
- "insert-array-item",
6984
- "remove-array-item",
6985
- "pop-array-item",
6986
- "shift-array-item"
6987
- ],
6988
7074
  forbidden: ["page", "row", "hidden"],
6989
7075
  message: "Rows cannot contain pages, other rows, or hidden fields. Hidden fields should be at page or form level."
6990
7076
  },
6991
7077
  group: {
6992
- allowed: [
6993
- "row",
6994
- "input",
6995
- "textarea",
6996
- "select",
6997
- "checkbox",
6998
- "multi-checkbox",
6999
- "radio",
7000
- "datepicker",
7001
- "toggle",
7002
- "slider",
7003
- "hidden",
7004
- "text",
7005
- "button",
7006
- "submit",
7007
- "next",
7008
- "previous",
7009
- "add-array-item",
7010
- "prepend-array-item",
7011
- "insert-array-item",
7012
- "remove-array-item",
7013
- "pop-array-item",
7014
- "shift-array-item"
7015
- ],
7016
7078
  forbidden: ["page", "group"],
7017
7079
  message: "Groups cannot contain pages or other groups (no nested groups)."
7018
7080
  },
7019
7081
  array: {
7020
- allowed: [
7021
- "row",
7022
- "group",
7023
- "input",
7024
- "textarea",
7025
- "select",
7026
- "checkbox",
7027
- "multi-checkbox",
7028
- "radio",
7029
- "datepicker",
7030
- "toggle",
7031
- "slider",
7032
- "hidden",
7033
- "text",
7034
- "button",
7035
- "submit",
7036
- "next",
7037
- "previous",
7038
- "add-array-item",
7039
- "prepend-array-item",
7040
- "insert-array-item",
7041
- "remove-array-item",
7042
- "pop-array-item",
7043
- "shift-array-item"
7044
- ],
7045
7082
  forbidden: ["page", "array"],
7046
7083
  message: "Arrays cannot contain pages or other arrays (no nested arrays)."
7084
+ },
7085
+ container: {
7086
+ forbidden: ["page"],
7087
+ message: "Containers cannot contain pages. Pages are top-level fields only."
7047
7088
  }
7048
7089
  };
7049
7090
  var EXPECTED_STRUCTURE = {
@@ -7055,7 +7096,8 @@ var EXPECTED_STRUCTURE = {
7055
7096
  row: `{ key: 'rowKey', type: 'row', fields: [...childFields] }`,
7056
7097
  group: `{ key: 'groupKey', type: 'group', fields: [...childFields] }`,
7057
7098
  array: `Full API: { key: 'arrayKey', type: 'array', fields: [...itemDefs] } OR Simplified API: { key: 'arrayKey', type: 'array', template: { type: 'input', label: 'Item' }, value: [] }`,
7058
- page: `{ key: 'pageKey', type: 'page', fields: [...childFields, { key: 'next', type: 'next', label: 'Next' }] }`
7099
+ page: `{ key: 'pageKey', type: 'page', fields: [...childFields, { key: 'next', type: 'next', label: 'Next' }] }`,
7100
+ container: `{ key: 'containerKey', type: 'container', wrappers: [{ type: 'css', cssClasses: 'card' }], fields: [...childFields] }`
7059
7101
  };
7060
7102
  function preValidateConfig(config) {
7061
7103
  const errors = [];
@@ -7100,7 +7142,7 @@ function preValidateConfig(config) {
7100
7142
  }
7101
7143
  });
7102
7144
  }
7103
- if (["row", "group", "array"].includes(fieldType || "")) {
7145
+ if (["row", "group", "array", "container"].includes(fieldType || "")) {
7104
7146
  for (const prop of INVALID_CONTAINER_PROPS) {
7105
7147
  if (prop in f) {
7106
7148
  errors.push({
@@ -7117,10 +7159,30 @@ function preValidateConfig(config) {
7117
7159
  const expected = EXPECTED_STRUCTURE[fieldType || ""] || "";
7118
7160
  errors.push({
7119
7161
  path: `${path}.${prop}`,
7120
- message: `"${fieldType}" containers do NOT support "${prop}". Containers don't hold values or validate - they are purely for layout/grouping.${expected ? ` Expected structure: ${expected}` : ""}`
7162
+ message: `"${fieldType}" containers do NOT support "${prop}". Containers don't hold values - they are purely for layout/grouping.${expected ? ` Expected structure: ${expected}` : ""}`
7121
7163
  });
7122
7164
  }
7123
7165
  }
7166
+ if (!VALIDATING_CONTAINERS.includes(fieldType || "")) {
7167
+ for (const prop of CONTAINER_VALIDATION_PROPS) {
7168
+ if (prop in f) {
7169
+ errors.push({
7170
+ path: `${path}.${prop}`,
7171
+ message: `"${fieldType}" containers do NOT support "${prop}". They flatten into their parent and have no schema path, so a container-level validator would have no value to run against. Use "group" or "array" for cross-field rules, or move the rule onto a child field.`
7172
+ });
7173
+ }
7174
+ }
7175
+ }
7176
+ if (fieldType !== "array") {
7177
+ for (const prop of ARRAY_SIZE_PROPS) {
7178
+ if (prop in f) {
7179
+ errors.push({
7180
+ path: `${path}.${prop}`,
7181
+ message: `"${fieldType}" containers do NOT support "${prop}". Array size constraints apply to "array" fields only.`
7182
+ });
7183
+ }
7184
+ }
7185
+ }
7124
7186
  if ("logic" in f && Array.isArray(f["logic"])) {
7125
7187
  const nonHiddenLogic = f["logic"].filter(
7126
7188
  (l) => l && typeof l === "object" && l["type"] !== "hidden"
@@ -7151,6 +7213,14 @@ function preValidateConfig(config) {
7151
7213
  });
7152
7214
  }
7153
7215
  }
7216
+ for (const prop of [...CONTAINER_VALIDATION_PROPS, ...ARRAY_SIZE_PROPS]) {
7217
+ if (prop in f) {
7218
+ errors.push({
7219
+ path: `${path}.${prop}`,
7220
+ message: `"page" containers do NOT support "${prop}". Pages flatten into the form and have no schema path of their own.`
7221
+ });
7222
+ }
7223
+ }
7154
7224
  }
7155
7225
  if (parentType && NESTING_RULES[parentType]) {
7156
7226
  const rules = NESTING_RULES[parentType];
@@ -7231,7 +7301,7 @@ function preValidateConfig(config) {
7231
7301
  });
7232
7302
  }
7233
7303
  }
7234
- if (["row", "group", "page"].includes(fieldType || "")) {
7304
+ if (["row", "group", "page", "container"].includes(fieldType || "")) {
7235
7305
  if (!("fields" in f)) {
7236
7306
  errors.push({
7237
7307
  path: `${path}.fields`,
@@ -7244,6 +7314,19 @@ function preValidateConfig(config) {
7244
7314
  });
7245
7315
  }
7246
7316
  }
7317
+ if (fieldType === "container") {
7318
+ if (!("wrappers" in f)) {
7319
+ errors.push({
7320
+ path: `${path}.wrappers`,
7321
+ message: `"container" container "${fieldKey || "unknown"}" is MISSING required "wrappers" property. Add a wrappers array naming the UI chrome to wrap the children in, or [] for no chrome. Do NOT switch to a "group" instead: a container flattens its children into the parent value, while a group nests them under its own key and owns a schema path, so the submitted value shape and validation behaviour both change. Expected structure: ${EXPECTED_STRUCTURE["container"]}`
7322
+ });
7323
+ } else if (!Array.isArray(f["wrappers"])) {
7324
+ errors.push({
7325
+ path: `${path}.wrappers`,
7326
+ message: `"container" container "${fieldKey || "unknown"}" has invalid "wrappers" - must be an array of wrapper objects, not ${typeof f["wrappers"]}.`
7327
+ });
7328
+ }
7329
+ }
7247
7330
  if (fieldType === "array") {
7248
7331
  const hasFields = "fields" in f;
7249
7332
  const hasTemplate = "template" in f;
@@ -8078,7 +8161,7 @@ function registerResources(server) {
8078
8161
  }
8079
8162
 
8080
8163
  // packages/dynamic-form-mcp/src/tools/lookup.tool.ts
8081
- import { z as z56 } from "zod";
8164
+ import { z as z57 } from "zod";
8082
8165
 
8083
8166
  // packages/dynamic-form-mcp/src/tools/data/lookup-topics.ts
8084
8167
  var TOPICS = {
@@ -9813,25 +9896,42 @@ provideDynamicForm({
9813
9896
  | FieldContext | \`ctx.value()\` | \`ctx.valueOf('path' as never)\` | custom validators |`
9814
9897
  },
9815
9898
  containers: {
9816
- brief: `| Container | Label? | Logic? | Notes |
9817
- |-----------|--------|--------|-------|
9818
- | page | NO | hidden only | Nav buttons INSIDE |
9819
- | group | NO | hidden only | Creates nested object |
9820
- | array | NO | hidden only | Two APIs: \`template\`+\`value\` (simplified) or \`fields\` (full) |
9821
- | row | NO | hidden only | Layout only |`,
9899
+ brief: `| Container | Label? | Logic? | Value | Notes |
9900
+ |-----------|--------|--------|-------|-------|
9901
+ | page | NO | hidden only | flattened | Nav buttons INSIDE |
9902
+ | group | NO | hidden only | nested under its key | Creates nested object |
9903
+ | array | NO | hidden only | nested under its key | Two APIs: \`template\`+\`value\` (simplified) or \`fields\` (full) |
9904
+ | row | NO | hidden only | flattened | Layout only |
9905
+ | container | NO | hidden only | flattened | Layout + REQUIRED \`wrappers\` chain |`,
9822
9906
  full: `# Container Rules
9823
9907
 
9824
- | Container | Label? | Logic? | Allowed Children | Notes |
9825
- |-----------|--------|--------|------------------|-------|
9826
- | page | NO | YES (hidden only) | rows, groups, arrays, leaf fields, buttons | Nav buttons go INSIDE |
9827
- | group | NO | YES (hidden only) | rows, arrays, leaf fields (NOT pages, groups) | Creates nested object |
9828
- | array | NO | YES (hidden only) | rows, groups, leaf fields (NOT pages, arrays) | Two APIs: \`template\`+\`value\` (simplified) or \`fields\` (full) |
9829
- | row | NO | YES (hidden only) | groups, arrays, containers, nested rows, hidden fields, leaf fields (NOT pages) | Layout only |
9908
+ | Container | Label? | Logic? | Value Handling | Allowed Children | Notes |
9909
+ |-----------|--------|--------|----------------|------------------|-------|
9910
+ | page | NO | YES (hidden only) | flattened | rows, groups, arrays, containers, hidden, leaf fields, buttons (NOT pages) | Nav buttons go INSIDE |
9911
+ | group | NO | YES (hidden only) | nested under its key | rows, arrays, containers, hidden, leaf fields, buttons (NOT pages, groups) | Creates nested object |
9912
+ | array | NO | YES (hidden only) | nested under its key | rows, groups, containers, hidden, leaf fields, buttons (NOT pages, arrays) | Two APIs: \`template\`+\`value\` (simplified) or \`fields\` (full) |
9913
+ | row | NO | YES (hidden only) | flattened | groups, arrays, containers, leaf fields, buttons (NOT pages, nested rows, hidden) | Layout only |
9914
+ | container | NO | YES (hidden only) | flattened | rows, groups, arrays, nested containers, hidden, leaf fields, buttons (NOT pages) | \`wrappers\` is REQUIRED (use [] for none) |
9915
+
9916
+ **Value handling decides which container you want.** \`page\`, \`row\` and \`container\` flatten: their children land directly in the parent value, and the container key never appears in the submitted data. \`group\` and \`array\` nest their children under their own key.
9917
+
9918
+ That difference is not cosmetic, so these are not interchangeable:
9919
+
9920
+ \`\`\`typescript
9921
+ // container \u2192 { street: '', city: '' } (chrome only, key not in the value)
9922
+ { key: 'billing', type: 'container', wrappers: [{ type: 'css', cssClasses: 'card' }], fields: [street, city] }
9923
+
9924
+ // group \u2192 { billing: { street: '', city: '' } } (adds a level to the value)
9925
+ { key: 'billing', type: 'group', fields: [street, city] }
9926
+ \`\`\`
9927
+
9928
+ Only \`group\` and \`array\` own a schema path, so only they take container-level \`validators\`, \`required\` and \`validationMessages\`. Reach for \`container\` when you want chrome around fields without changing the data shape, and for \`group\` when you want the nesting or the cross-field validation.
9830
9929
 
9831
9930
  **CRITICAL:**
9832
- - All containers (page, group, row, array) support only the \`hidden\` logic type for conditional visibility.
9931
+ - All containers (page, group, row, array, container) support only the \`hidden\` logic type for conditional visibility.
9833
9932
  - For other logic types (disabled, required, readonly, derivation), apply them to child fields instead.
9834
- - Pages cannot be nested - ALL top-level fields must be pages if using multi-page mode.`
9933
+ - Pages cannot be nested - ALL top-level fields must be pages if using multi-page mode.
9934
+ - Rows reject nested rows and hidden fields; put hidden fields at page or form level.`
9835
9935
  },
9836
9936
  "field-placement": {
9837
9937
  brief: `**Multi-page:** ALL root fields must be pages. Hidden fields go INSIDE first page.
@@ -10625,7 +10725,8 @@ var TOPIC_DESCRIPTIONS = {
10625
10725
  "field-placement": "Which fields can go where \u2014 nesting and placement rules",
10626
10726
  "logic-matrix": "Which logic types are supported on which field types",
10627
10727
  "context-api": "FieldContext API \u2014 valueOf(), formValue, parent, arrayIndex",
10628
- containers: "Overview of all container types (group, row, array, page)",
10728
+ containers: "Overview of all container types (group, row, array, container, page) and what each may hold",
10729
+ container: "Wraps children in a wrapper chain; flattens their values into the parent like a row",
10629
10730
  "array-buttons": "Add/remove array item button configuration",
10630
10731
  "custom-validators": "Custom validator functions via validators array",
10631
10732
  conditions: "Condition operators and types for logic rules",
@@ -10885,7 +10986,7 @@ function formatTopicItem(key) {
10885
10986
  }
10886
10987
  function getTopicList() {
10887
10988
  const fieldTypes = ["input", "select", "slider", "radio", "checkbox", "textarea", "datepicker", "toggle", "text", "hidden"];
10888
- const containers = ["group", "row", "array", "simplified-array", "page"];
10989
+ const containers = [...getFieldTypesByCategory("container").map((f) => f.type), "simplified-array"];
10889
10990
  const wrappers = ["wrappers", ...getWrappers().map((w) => w.type)];
10890
10991
  const addons = ["addons", ...getAddonTypes().map((k) => k.type)];
10891
10992
  const concepts = [
@@ -10941,7 +11042,7 @@ ${patterns.map(formatTopicItem).join("\n")}
10941
11042
  }
10942
11043
  function formatFieldInfoFull(field, uiFieldType) {
10943
11044
  const lines = [];
10944
- const isContainer = ["row", "group", "array", "page"].includes(field.type);
11045
+ const isContainer = field.category === "container";
10945
11046
  const isHidden = field.type === "hidden";
10946
11047
  lines.push(`## ${field.type} field`);
10947
11048
  lines.push("");
@@ -11370,11 +11471,11 @@ Patterns: field-placement, logic-matrix, context-api, containers, multi-page-got
11370
11471
  Use topic="list" to see all available topics with descriptions.
11371
11472
  Use ngforge_search query="your question" to find topics by keyword.`,
11372
11473
  {
11373
- topic: z56.string().describe(
11374
- 'Topic to look up: field types (input, select, hidden, group, row, array, page), wrappers (wrappers, css, section, arraySection), concepts (validation, conditional, derivation, property-derivation, options-format), patterns (golden-path, pitfalls, multi-page-gotchas), or "list" to see all topics'
11474
+ topic: z57.string().describe(
11475
+ 'Topic to look up: field types (input, select, hidden, group, row, array, container, page), wrappers (wrappers, css, section, arraySection), concepts (validation, conditional, derivation, property-derivation, options-format), patterns (golden-path, pitfalls, multi-page-gotchas), or "list" to see all topics'
11375
11476
  ),
11376
- depth: z56.enum(["brief", "full", "schema"]).default("full").describe("brief=quick syntax (~20 lines), full=complete docs with examples, schema=include JSON schema"),
11377
- uiIntegration: z56.enum(UI_INTEGRATIONS2).optional().describe("Filter UI-specific info (only with depth=schema). material, bootstrap, primeng, ionic")
11477
+ depth: z57.enum(["brief", "full", "schema"]).default("full").describe("brief=quick syntax (~20 lines), full=complete docs with examples, schema=include JSON schema"),
11478
+ uiIntegration: z57.enum(UI_INTEGRATIONS2).optional().describe("Filter UI-specific info (only with depth=schema). material, bootstrap, primeng, ionic")
11378
11479
  },
11379
11480
  async ({ topic, depth, uiIntegration }) => {
11380
11481
  const normalizedTopic = topic.toLowerCase().trim();
@@ -11422,7 +11523,7 @@ ${nextSteps}`;
11422
11523
  }
11423
11524
 
11424
11525
  // packages/dynamic-form-mcp/src/tools/examples.tool.ts
11425
- import { z as z57 } from "zod";
11526
+ import { z as z58 } from "zod";
11426
11527
  var PATTERNS = {
11427
11528
  // ========== MINIMAL PATTERNS (NEW) ==========
11428
11529
  "minimal-multipage": {
@@ -13687,10 +13788,10 @@ Standard patterns: derivation, property-derivation, multi-page, conditional, val
13687
13788
  Use pattern="list" to see all available patterns.
13688
13789
  Use depth="minimal" for code-only output (no markdown).`,
13689
13790
  {
13690
- pattern: z57.string().optional().describe(
13791
+ pattern: z58.string().optional().describe(
13691
13792
  'Pattern to get: minimal-multipage, minimal-array, minimal-simplified-array, minimal-conditional, minimal-validation, minimal-hidden, derivation, property-derivation, multi-page, conditional, validation, complete, mega. Use "list" to see all.'
13692
13793
  ),
13693
- depth: z57.enum(["minimal", "brief", "full", "explained"]).default("full").describe(
13794
+ depth: z58.enum(["minimal", "brief", "full", "explained"]).default("full").describe(
13694
13795
  "minimal=code only (~20-50 lines), brief=code+summary, full=code+comments (default), explained=code+detailed explanation"
13695
13796
  )
13696
13797
  },
@@ -13755,7 +13856,7 @@ function extractCode(markdown) {
13755
13856
  }
13756
13857
 
13757
13858
  // packages/dynamic-form-mcp/src/tools/validate.tool.ts
13758
- import { z as z58 } from "zod";
13859
+ import { z as z59 } from "zod";
13759
13860
  var UI_INTEGRATIONS3 = ["material", "bootstrap", "primeng", "ionic"];
13760
13861
  var ERROR_TOPIC_HINTS = [
13761
13862
  { pattern: /options/i, hint: '`ngforge_lookup topic="options-format"` \u2014 correct options syntax' },
@@ -13808,10 +13909,10 @@ Example errors you'll see:
13808
13909
  - "options MUST be at FIELD level, NOT inside props"
13809
13910
  - "containers only support 'hidden' logic type"`,
13810
13911
  {
13811
- config: z58.union([z58.string(), z58.object({}).passthrough()]).describe(
13912
+ config: z59.union([z59.string(), z59.object({}).passthrough()]).describe(
13812
13913
  "File path (.ts/.js) OR JSON string OR JSON object. Auto-detects: paths ending in .ts/.js or starting with / are treated as files."
13813
13914
  ),
13814
- uiIntegration: z58.enum(UI_INTEGRATIONS3).default("material").describe("UI library to validate against (material, bootstrap, primeng, ionic). Defaults to material.")
13915
+ uiIntegration: z59.enum(UI_INTEGRATIONS3).default("material").describe("UI library to validate against (material, bootstrap, primeng, ionic). Defaults to material.")
13815
13916
  },
13816
13917
  async ({ config, uiIntegration }) => {
13817
13918
  try {
@@ -13903,7 +14004,7 @@ If validating JSON, ensure:
13903
14004
  }
13904
14005
 
13905
14006
  // packages/dynamic-form-mcp/src/tools/scaffold.tool.ts
13906
- import { z as z59 } from "zod";
14007
+ import { z as z60 } from "zod";
13907
14008
  var UI_INTEGRATIONS4 = ["material", "bootstrap", "primeng", "ionic"];
13908
14009
  function parseFieldDefs(fields) {
13909
14010
  return fields.map((f) => {
@@ -14158,12 +14259,12 @@ Examples:
14158
14259
  - With groups: pages=0 groups=["address","billing"]
14159
14260
  - With hidden: hidden=["userId:abc123","source:web"]`,
14160
14261
  {
14161
- pages: z59.number().min(0).max(10).default(0).describe("Number of pages (0 = single-page form, 1-10 = multi-page wizard)"),
14162
- arrays: z59.array(z59.string()).optional().describe('Array field names for dynamic lists, e.g., ["contacts", "addresses"]'),
14163
- groups: z59.array(z59.string()).optional().describe('Group field names for nested objects, e.g., ["address", "billing"]'),
14164
- hidden: z59.array(z59.string()).optional().describe('Hidden fields as "name:value" pairs, e.g., ["userId:abc", "version:1"]'),
14165
- fields: z59.array(z59.string()).optional().describe('Basic fields as "name:type" pairs, e.g., ["email:input", "country:select", "age:slider"]'),
14166
- uiIntegration: z59.enum(UI_INTEGRATIONS4).default("material").describe("UI library (for future UI-specific props). Defaults to material.")
14262
+ pages: z60.number().min(0).max(10).default(0).describe("Number of pages (0 = single-page form, 1-10 = multi-page wizard)"),
14263
+ arrays: z60.array(z60.string()).optional().describe('Array field names for dynamic lists, e.g., ["contacts", "addresses"]'),
14264
+ groups: z60.array(z60.string()).optional().describe('Group field names for nested objects, e.g., ["address", "billing"]'),
14265
+ hidden: z60.array(z60.string()).optional().describe('Hidden fields as "name:value" pairs, e.g., ["userId:abc", "version:1"]'),
14266
+ fields: z60.array(z60.string()).optional().describe('Basic fields as "name:type" pairs, e.g., ["email:input", "country:select", "age:slider"]'),
14267
+ uiIntegration: z60.enum(UI_INTEGRATIONS4).default("material").describe("UI library (for future UI-specific props). Defaults to material.")
14167
14268
  },
14168
14269
  async ({ pages, arrays = [], groups = [], hidden = [], fields = [] }) => {
14169
14270
  const fieldDefs = parseFieldDefs(fields);
@@ -14205,11 +14306,11 @@ Examples:
14205
14306
  }
14206
14307
 
14207
14308
  // packages/dynamic-form-mcp/src/tools/search.tool.ts
14208
- import { z as z60 } from "zod";
14309
+ import { z as z61 } from "zod";
14209
14310
  var searchIndex = null;
14210
14311
  function getTopicSubcategory(key) {
14211
14312
  const fieldTypes = ["input", "select", "slider", "radio", "checkbox", "textarea", "datepicker", "toggle", "text", "hidden"];
14212
- const containers = ["group", "row", "array", "simplified-array", "page"];
14313
+ const containers = [...getFieldTypesByCategory("container").map((f) => f.type), "simplified-array"];
14213
14314
  const concepts = [
14214
14315
  "validation",
14215
14316
  "validation-messages",
@@ -14249,6 +14350,19 @@ function buildIndex() {
14249
14350
  toolCall: `ngforge_lookup topic="${key}"`
14250
14351
  });
14251
14352
  }
14353
+ for (const field of getFieldTypes()) {
14354
+ if (TOPICS[field.type]) continue;
14355
+ const description = TOPIC_DESCRIPTIONS[field.type] || field.description;
14356
+ entries.push({
14357
+ id: field.type,
14358
+ category: "topic",
14359
+ subcategory: getTopicSubcategory(field.type),
14360
+ description,
14361
+ aliases: aliasMap[field.type] || [],
14362
+ content: `${description} ${field.description}`.toLowerCase(),
14363
+ toolCall: `ngforge_lookup topic="${field.type}"`
14364
+ });
14365
+ }
14252
14366
  for (const [key, pattern] of Object.entries(PATTERNS)) {
14253
14367
  entries.push({
14254
14368
  id: key,
@@ -14353,7 +14467,7 @@ Use this when you don't know the exact topic name.
14353
14467
 
14354
14468
  New to ng-forge? Start with: ngforge_lookup topic="workflow"`,
14355
14469
  {
14356
- query: z60.string().describe("Natural language or keywords to search for")
14470
+ query: z61.string().describe("Natural language or keywords to search for")
14357
14471
  },
14358
14472
  async ({ query }) => {
14359
14473
  const index = buildIndex();