{"version":3,"sources":["../src/browser.ts","../src/defaults.ts","../src/validators/field-types.ts","../src/validators/layout.ts","../src/validators/field-options.ts","../src/validators/formspec.ts"],"sourcesContent":["/**\n * Browser-safe exports from @formspec/config.\n *\n * This entry point excludes the file-based config loader (loadConfig)\n * which requires Node.js APIs. Use this entry point for browser builds.\n *\n * For browser use:\n * - Use loadConfigFromString() to parse YAML config strings\n * - Use defineConstraints() for programmatic configuration\n * - Use validateFormSpec() for validation\n *\n * @packageDocumentation\n */\n\n// Re-export types\nexport type {\n  Severity,\n  FieldTypeConstraints,\n  LayoutConstraints,\n  LayoutTypeConstraints,\n  RuleEffectConstraints,\n  RuleConstraints,\n  UISchemaConstraints,\n  FieldOptionConstraints,\n  ControlOptionConstraints,\n  ConstraintConfig,\n  ResolvedConstraintConfig,\n  ResolvedUISchemaConstraints,\n  ResolvedRuleConstraints,\n  FormSpecConfig,\n  ValidationIssue,\n  ValidationResult,\n} from \"./types.js\";\n\n// Re-export browser-safe loader functions\n// These are defined inline to avoid pulling in Node.js imports from loader.ts\nimport { parse as parseYaml } from \"yaml\";\nimport type { FormSpecConfig, ConstraintConfig, ResolvedConstraintConfig } from \"./types.js\";\nimport { mergeWithDefaults, DEFAULT_CONSTRAINTS, DEFAULT_CONFIG } from \"./defaults.js\";\n\n// Re-export defaults\nexport { DEFAULT_CONSTRAINTS, DEFAULT_CONFIG, mergeWithDefaults };\n\n/**\n * Synchronously loads config from a pre-parsed YAML string.\n * Useful for browser environments or when config is already available.\n *\n * @param yamlContent - The YAML content to parse\n * @returns The parsed and merged configuration\n */\nexport function loadConfigFromString(yamlContent: string): ResolvedConstraintConfig {\n  const parsed = parseYaml(yamlContent) as FormSpecConfig | null | undefined;\n\n  if (parsed === null || parsed === undefined) {\n    return mergeWithDefaults(undefined);\n  }\n\n  if (typeof parsed !== \"object\" || Array.isArray(parsed)) {\n    throw new Error(`Invalid config content: expected an object, got ${typeof parsed}`);\n  }\n\n  return mergeWithDefaults(parsed.constraints);\n}\n\n/**\n * Creates a constraint configuration directly from an object.\n * Useful for programmatic configuration without YAML.\n *\n * @param config - Partial constraint configuration\n * @returns Complete configuration with defaults applied\n *\n * @example\n * ```ts\n * const config = defineConstraints({\n *   fieldTypes: {\n *     dynamicEnum: 'error',\n *     dynamicSchema: 'error',\n *   },\n *   layout: {\n *     group: 'error',\n *   },\n * });\n * ```\n */\nexport function defineConstraints(config: ConstraintConfig): ResolvedConstraintConfig {\n  return mergeWithDefaults(config);\n}\n\n// Re-export validators (these are all browser-safe)\nexport {\n  validateFormSpecElements,\n  validateFormSpec,\n  type FormSpecValidationOptions,\n} from \"./validators/formspec.js\";\n\nexport {\n  validateFieldTypes,\n  isFieldTypeAllowed,\n  getFieldTypeSeverity,\n  type FieldTypeContext,\n} from \"./validators/field-types.js\";\n\nexport {\n  validateLayout,\n  isLayoutTypeAllowed,\n  isNestingDepthAllowed,\n  type LayoutContext,\n} from \"./validators/layout.js\";\n\nexport {\n  validateFieldOptions,\n  extractFieldOptions,\n  isFieldOptionAllowed,\n  getFieldOptionSeverity,\n  type FieldOptionsContext,\n  type FieldOption,\n} from \"./validators/field-options.js\";\n","import type { ConstraintConfig, FormSpecConfig, ResolvedConstraintConfig } from \"./types.js\";\n\n/**\n * Default constraint configuration that allows all features.\n * All constraints default to \"off\" (allowed).\n *\n * @beta\n */\nexport const DEFAULT_CONSTRAINTS: ResolvedConstraintConfig = {\n  fieldTypes: {\n    text: \"off\",\n    number: \"off\",\n    boolean: \"off\",\n    staticEnum: \"off\",\n    dynamicEnum: \"off\",\n    dynamicSchema: \"off\",\n    array: \"off\",\n    object: \"off\",\n  },\n  layout: {\n    group: \"off\",\n    conditionals: \"off\",\n    maxNestingDepth: Infinity,\n  },\n  uiSchema: {\n    layouts: {\n      VerticalLayout: \"off\",\n      HorizontalLayout: \"off\",\n      Group: \"off\",\n      Categorization: \"off\",\n      Category: \"off\",\n    },\n    rules: {\n      enabled: \"off\",\n      effects: {\n        SHOW: \"off\",\n        HIDE: \"off\",\n        ENABLE: \"off\",\n        DISABLE: \"off\",\n      },\n    },\n  },\n  fieldOptions: {\n    label: \"off\",\n    placeholder: \"off\",\n    required: \"off\",\n    minValue: \"off\",\n    maxValue: \"off\",\n    minItems: \"off\",\n    maxItems: \"off\",\n  },\n  controlOptions: {\n    format: \"off\",\n    readonly: \"off\",\n    multi: \"off\",\n    showUnfocusedDescription: \"off\",\n    hideRequiredAsterisk: \"off\",\n    custom: {},\n  },\n};\n\n/**\n * Default FormSpec configuration.\n *\n * @beta\n */\nexport const DEFAULT_CONFIG: FormSpecConfig = {\n  constraints: DEFAULT_CONSTRAINTS,\n};\n\n/**\n * Merges user constraints with defaults, filling in any missing values.\n *\n * @beta\n */\nexport function mergeWithDefaults(config: ConstraintConfig | undefined): ResolvedConstraintConfig {\n  if (!config) {\n    return DEFAULT_CONSTRAINTS;\n  }\n\n  return {\n    fieldTypes: {\n      ...DEFAULT_CONSTRAINTS.fieldTypes,\n      ...config.fieldTypes,\n    },\n    layout: {\n      ...DEFAULT_CONSTRAINTS.layout,\n      ...config.layout,\n    },\n    uiSchema: {\n      layouts: {\n        ...DEFAULT_CONSTRAINTS.uiSchema.layouts,\n        ...config.uiSchema?.layouts,\n      },\n      rules: {\n        enabled: config.uiSchema?.rules?.enabled ?? DEFAULT_CONSTRAINTS.uiSchema.rules.enabled,\n        effects: {\n          ...DEFAULT_CONSTRAINTS.uiSchema.rules.effects,\n          ...config.uiSchema?.rules?.effects,\n        },\n      },\n    },\n    fieldOptions: {\n      ...DEFAULT_CONSTRAINTS.fieldOptions,\n      ...config.fieldOptions,\n    },\n    controlOptions: {\n      ...DEFAULT_CONSTRAINTS.controlOptions,\n      ...config.controlOptions,\n      custom: {\n        ...DEFAULT_CONSTRAINTS.controlOptions.custom,\n        ...config.controlOptions?.custom,\n      },\n    },\n  };\n}\n","import type { FieldTypeConstraints, Severity, ValidationIssue } from \"../types.js\";\n\n/**\n * Maps FormSpec field._field values to constraint config keys.\n */\nconst FIELD_TYPE_MAP: Record<string, keyof FieldTypeConstraints> = {\n  text: \"text\",\n  number: \"number\",\n  boolean: \"boolean\",\n  enum: \"staticEnum\",\n  dynamic_enum: \"dynamicEnum\",\n  dynamic_schema: \"dynamicSchema\",\n  array: \"array\",\n  object: \"object\",\n};\n\n/**\n * Human-readable names for field types.\n */\nconst FIELD_TYPE_NAMES: Record<string, string> = {\n  text: \"text field\",\n  number: \"number field\",\n  boolean: \"boolean field\",\n  enum: \"static enum field\",\n  dynamic_enum: \"dynamic enum field\",\n  dynamic_schema: \"dynamic schema field\",\n  array: \"array field\",\n  object: \"object field\",\n};\n\n/**\n * Context for field type validation.\n *\n * @beta\n */\nexport interface FieldTypeContext {\n  /** The _field discriminator value (e.g., \"text\", \"number\", \"enum\") */\n  fieldType: string;\n  /** The field name */\n  fieldName: string;\n  /** Optional path for nested fields */\n  path?: string;\n}\n\n/**\n * Validates a field type against constraints.\n *\n * @param context - Information about the field being validated\n * @param constraints - Field type constraints\n * @returns Array of validation issues (empty if valid)\n *\n * @beta\n */\nexport function validateFieldTypes(\n  context: FieldTypeContext,\n  constraints: FieldTypeConstraints\n): ValidationIssue[] {\n  const issues: ValidationIssue[] = [];\n\n  const constraintKey = FIELD_TYPE_MAP[context.fieldType];\n  if (!constraintKey) {\n    // Unknown field type, skip validation\n    return issues;\n  }\n\n  const severity = constraints[constraintKey];\n  if (severity && severity !== \"off\") {\n    const fieldTypeName = FIELD_TYPE_NAMES[context.fieldType] ?? context.fieldType;\n    issues.push(createFieldTypeIssue(context, fieldTypeName, severity));\n  }\n\n  return issues;\n}\n\n/**\n * Creates a validation issue for a disallowed field type.\n */\nfunction createFieldTypeIssue(\n  context: FieldTypeContext,\n  fieldTypeName: string,\n  severity: Severity\n): ValidationIssue {\n  const path = context.path ?? context.fieldName;\n  return {\n    code: \"DISALLOWED_FIELD_TYPE\",\n    message: `Field \"${context.fieldName}\" uses ${fieldTypeName}, which is not allowed in this project`,\n    severity: severity === \"error\" ? \"error\" : \"warning\",\n    category: \"fieldTypes\",\n    path,\n    fieldName: context.fieldName,\n    fieldType: context.fieldType,\n  };\n}\n\n/**\n * Checks if a field type is allowed by the constraints.\n * Useful for quick checks without generating issues.\n *\n * @param fieldType - The _field discriminator value\n * @param constraints - Field type constraints\n * @returns true if allowed, false if disallowed\n *\n * @beta\n */\nexport function isFieldTypeAllowed(fieldType: string, constraints: FieldTypeConstraints): boolean {\n  const constraintKey = FIELD_TYPE_MAP[fieldType];\n  if (!constraintKey) {\n    return true; // Unknown types are allowed by default\n  }\n\n  const severity = constraints[constraintKey];\n  return !severity || severity === \"off\";\n}\n\n/**\n * Gets the severity level for a field type.\n *\n * @param fieldType - The _field discriminator value\n * @param constraints - Field type constraints\n * @returns Severity level, or \"off\" if not constrained\n *\n * @beta\n */\nexport function getFieldTypeSeverity(\n  fieldType: string,\n  constraints: FieldTypeConstraints\n): Severity {\n  const constraintKey = FIELD_TYPE_MAP[fieldType];\n  if (!constraintKey) {\n    return \"off\";\n  }\n\n  return constraints[constraintKey] ?? \"off\";\n}\n","import type { LayoutConstraints, Severity, ValidationIssue } from \"../types.js\";\n\n/**\n * Context for layout validation.\n *\n * @beta\n */\nexport interface LayoutContext {\n  /** The type of layout element (\"group\" | \"conditional\") */\n  layoutType: \"group\" | \"conditional\";\n  /** Optional label for the element (for groups) */\n  label?: string;\n  /** Current nesting depth */\n  depth: number;\n  /** Path to this element */\n  path?: string;\n}\n\n/**\n * Validates a layout element against constraints.\n *\n * @param context - Information about the layout element\n * @param constraints - Layout constraints\n * @returns Array of validation issues (empty if valid)\n *\n * @beta\n */\nexport function validateLayout(\n  context: LayoutContext,\n  constraints: LayoutConstraints\n): ValidationIssue[] {\n  const issues: ValidationIssue[] = [];\n\n  // Check if groups are allowed\n  if (context.layoutType === \"group\") {\n    const groupSeverity = constraints.group;\n    if (groupSeverity && groupSeverity !== \"off\") {\n      issues.push(createGroupIssue(context, groupSeverity));\n    }\n  }\n\n  // Check if conditionals are allowed\n  if (context.layoutType === \"conditional\") {\n    const conditionalSeverity = constraints.conditionals;\n    if (conditionalSeverity && conditionalSeverity !== \"off\") {\n      issues.push(createConditionalIssue(context, conditionalSeverity));\n    }\n  }\n\n  // Check nesting depth (applies to both groups and fields within nested structures)\n  const maxDepth = constraints.maxNestingDepth;\n  if (maxDepth !== undefined && context.depth > maxDepth) {\n    issues.push(createNestingDepthIssue(context, maxDepth));\n  }\n\n  return issues;\n}\n\n/**\n * Creates a validation issue for a disallowed group.\n */\nfunction createGroupIssue(context: LayoutContext, severity: Severity): ValidationIssue {\n  const labelInfo = context.label ? ` \"${context.label}\"` : \"\";\n  const issue: ValidationIssue = {\n    code: \"DISALLOWED_GROUP\",\n    message: `Group${labelInfo} is not allowed - visual grouping is not supported in this project`,\n    severity: severity === \"error\" ? \"error\" : \"warning\",\n    category: \"layout\",\n  };\n  if (context.path !== undefined) {\n    issue.path = context.path;\n  }\n  return issue;\n}\n\n/**\n * Creates a validation issue for a disallowed conditional.\n */\nfunction createConditionalIssue(context: LayoutContext, severity: Severity): ValidationIssue {\n  const issue: ValidationIssue = {\n    code: \"DISALLOWED_CONDITIONAL\",\n    message: `Conditional visibility (when/is) is not allowed in this project`,\n    severity: severity === \"error\" ? \"error\" : \"warning\",\n    category: \"layout\",\n  };\n  if (context.path !== undefined) {\n    issue.path = context.path;\n  }\n  return issue;\n}\n\n/**\n * Creates a validation issue for exceeding nesting depth.\n */\nfunction createNestingDepthIssue(context: LayoutContext, maxDepth: number): ValidationIssue {\n  const issue: ValidationIssue = {\n    code: \"EXCEEDED_NESTING_DEPTH\",\n    message: `Nesting depth ${String(context.depth)} exceeds maximum allowed depth of ${String(maxDepth)}`,\n    severity: \"error\",\n    category: \"layout\",\n  };\n  if (context.path !== undefined) {\n    issue.path = context.path;\n  }\n  return issue;\n}\n\n/**\n * Checks if a layout type is allowed by the constraints.\n *\n * @param layoutType - The type of layout element\n * @param constraints - Layout constraints\n * @returns true if allowed, false if disallowed\n *\n * @beta\n */\nexport function isLayoutTypeAllowed(\n  layoutType: \"group\" | \"conditional\",\n  constraints: LayoutConstraints\n): boolean {\n  if (layoutType === \"group\") {\n    const severity = constraints.group;\n    return !severity || severity === \"off\";\n  }\n\n  // layoutType === \"conditional\"\n  const severity = constraints.conditionals;\n  return !severity || severity === \"off\";\n}\n\n/**\n * Checks if a nesting depth is allowed.\n *\n * @param depth - Current nesting depth\n * @param constraints - Layout constraints\n * @returns true if allowed, false if exceeds limit\n *\n * @beta\n */\nexport function isNestingDepthAllowed(depth: number, constraints: LayoutConstraints): boolean {\n  const maxDepth = constraints.maxNestingDepth;\n  if (maxDepth === undefined) {\n    return true;\n  }\n  return depth <= maxDepth;\n}\n","import type { FieldOptionConstraints, Severity, ValidationIssue } from \"../types.js\";\n\n/**\n * Known field options that can be validated.\n *\n * @beta\n */\nexport type FieldOption =\n  | \"label\"\n  | \"placeholder\"\n  | \"required\"\n  | \"minValue\"\n  | \"maxValue\"\n  | \"minItems\"\n  | \"maxItems\";\n\n/**\n * Context for field option validation.\n *\n * @beta\n */\nexport interface FieldOptionsContext {\n  /** The field name */\n  fieldName: string;\n  /** Which options are present on this field */\n  presentOptions: FieldOption[];\n  /** Path to this field */\n  path?: string;\n}\n\n/**\n * Validates field options against constraints.\n *\n * @param context - Information about the field and its options\n * @param constraints - Field option constraints\n * @returns Array of validation issues (empty if valid)\n *\n * @beta\n */\nexport function validateFieldOptions(\n  context: FieldOptionsContext,\n  constraints: FieldOptionConstraints\n): ValidationIssue[] {\n  const issues: ValidationIssue[] = [];\n\n  for (const option of context.presentOptions) {\n    const severity = constraints[option];\n    if (severity && severity !== \"off\") {\n      issues.push(createFieldOptionIssue(context, option, severity));\n    }\n  }\n\n  return issues;\n}\n\n/**\n * Creates a validation issue for a disallowed field option.\n */\nfunction createFieldOptionIssue(\n  context: FieldOptionsContext,\n  option: FieldOption,\n  severity: Severity\n): ValidationIssue {\n  const path = context.path ?? context.fieldName;\n  return {\n    code: \"DISALLOWED_FIELD_OPTION\",\n    message: `Field \"${context.fieldName}\" uses the \"${option}\" option, which is not allowed in this project`,\n    severity: severity === \"error\" ? \"error\" : \"warning\",\n    category: \"fieldOptions\",\n    path,\n    fieldName: context.fieldName,\n  };\n}\n\n/**\n * Extracts which options are present on a field object.\n * Works with FormSpec field types.\n *\n * @param field - A field object with potential options\n * @returns Array of present option names\n *\n * @beta\n */\nexport function extractFieldOptions(field: Record<string, unknown>): FieldOption[] {\n  const options: FieldOption[] = [];\n\n  if (field[\"label\"] !== undefined) options.push(\"label\");\n  if (field[\"placeholder\"] !== undefined) options.push(\"placeholder\");\n  if (field[\"required\"] !== undefined) options.push(\"required\");\n  // NumberField uses \"min\"/\"max\" in core types, map to \"minValue\"/\"maxValue\" constraints\n  if (field[\"min\"] !== undefined || field[\"minValue\"] !== undefined) options.push(\"minValue\");\n  if (field[\"max\"] !== undefined || field[\"maxValue\"] !== undefined) options.push(\"maxValue\");\n  if (field[\"minItems\"] !== undefined) options.push(\"minItems\");\n  if (field[\"maxItems\"] !== undefined) options.push(\"maxItems\");\n\n  return options;\n}\n\n/**\n * Checks if a specific field option is allowed.\n *\n * @param option - The option to check\n * @param constraints - Field option constraints\n * @returns true if allowed, false if disallowed\n *\n * @beta\n */\nexport function isFieldOptionAllowed(\n  option: FieldOption,\n  constraints: FieldOptionConstraints\n): boolean {\n  const severity = constraints[option];\n  return !severity || severity === \"off\";\n}\n\n/**\n * Gets the severity level for a field option.\n *\n * @param option - The option to check\n * @param constraints - Field option constraints\n * @returns Severity level, or \"off\" if not constrained\n *\n * @beta\n */\nexport function getFieldOptionSeverity(\n  option: FieldOption,\n  constraints: FieldOptionConstraints\n): Severity {\n  return constraints[option] ?? \"off\";\n}\n","import type { FormElement, FormSpec, AnyField } from \"@formspec/core\";\nimport type {\n  ConstraintConfig,\n  ResolvedConstraintConfig,\n  ValidationIssue,\n  ValidationResult,\n} from \"../types.js\";\nimport { mergeWithDefaults } from \"../defaults.js\";\nimport { validateFieldTypes } from \"./field-types.js\";\nimport { validateLayout } from \"./layout.js\";\nimport { validateFieldOptions, extractFieldOptions } from \"./field-options.js\";\n\n/**\n * Options for validating FormSpec elements.\n *\n * @public\n */\nexport interface FormSpecValidationOptions {\n  /** Constraint configuration (will be merged with defaults) */\n  constraints?: ConstraintConfig;\n}\n\n/**\n * Validates FormSpec elements against constraints.\n *\n * This is the main entry point for validating a form specification\n * against a constraint configuration. It walks through all elements\n * and checks each one against the configured constraints.\n *\n * @param elements - FormSpec elements to validate\n * @param options - Validation options including constraints\n * @returns Validation result with all issues found\n *\n * @example\n * ```ts\n * import { formspec, field, group } from '@formspec/dsl';\n * import { validateFormSpecElements, defineConstraints } from '@formspec/config';\n *\n * const form = formspec(\n *   group(\"Contact\",\n *     field.text(\"name\"),\n *     field.dynamicEnum(\"country\", \"countries\"),\n *   ),\n * );\n *\n * const result = validateFormSpecElements(form.elements, {\n *   constraints: {\n *     fieldTypes: { dynamicEnum: 'error' },\n *     layout: { group: 'error' },\n *   },\n * });\n *\n * if (!result.valid) {\n *   console.error('Validation failed:', result.issues);\n * }\n * ```\n *\n * @public\n */\nexport function validateFormSpecElements(\n  elements: readonly FormElement[],\n  options: FormSpecValidationOptions = {}\n): ValidationResult {\n  const constraints = mergeWithDefaults(options.constraints);\n  const issues: ValidationIssue[] = [];\n\n  // Walk through all elements\n  walkElements(elements, constraints, issues, \"\", 0);\n\n  return {\n    valid: !issues.some((issue) => issue.severity === \"error\"),\n    issues,\n  };\n}\n\n/**\n * Validates a complete FormSpec against constraints.\n *\n * @param formSpec - The FormSpec to validate\n * @param options - Validation options including constraints\n * @returns Validation result with all issues found\n *\n * @public\n */\nexport function validateFormSpec(\n  formSpec: FormSpec<readonly FormElement[]>,\n  options: FormSpecValidationOptions = {}\n): ValidationResult {\n  return validateFormSpecElements(formSpec.elements, options);\n}\n\n/**\n * Recursively walks through FormSpec elements and validates each one.\n */\nfunction walkElements(\n  elements: readonly FormElement[],\n  constraints: ResolvedConstraintConfig,\n  issues: ValidationIssue[],\n  pathPrefix: string,\n  depth: number\n): void {\n  for (const element of elements) {\n    const elementPath = pathPrefix;\n\n    if (element._type === \"field\") {\n      validateField(element, constraints, issues, elementPath, depth);\n    } else if (element._type === \"group\") {\n      validateGroup(element, constraints, issues, elementPath, depth);\n    } else {\n      // element._type === \"conditional\"\n      validateConditional(element, constraints, issues, elementPath, depth);\n    }\n  }\n}\n\n/**\n * Validates a field element.\n */\nfunction validateField(\n  field: AnyField,\n  constraints: ResolvedConstraintConfig,\n  issues: ValidationIssue[],\n  pathPrefix: string,\n  depth: number\n): void {\n  const fieldPath = pathPrefix ? `${pathPrefix}/${field.name}` : field.name;\n\n  // Validate field type\n  const fieldTypeIssues = validateFieldTypes(\n    {\n      fieldType: field._field,\n      fieldName: field.name,\n      path: fieldPath,\n    },\n    constraints.fieldTypes\n  );\n  issues.push(...fieldTypeIssues);\n\n  // Validate field options\n  const presentOptions = extractFieldOptions(field as unknown as Record<string, unknown>);\n  if (presentOptions.length > 0) {\n    const optionIssues = validateFieldOptions(\n      {\n        fieldName: field.name,\n        presentOptions,\n        path: fieldPath,\n      },\n      constraints.fieldOptions\n    );\n    issues.push(...optionIssues);\n  }\n\n  // Check nesting depth for array/object fields\n  if (field._field === \"array\" || field._field === \"object\") {\n    const layoutIssues = validateLayout(\n      {\n        layoutType: \"group\", // Arrays/objects contribute to nesting depth\n        depth: depth + 1,\n        path: fieldPath,\n      },\n      constraints.layout\n    );\n    // Only add nesting depth issues, not group issues\n    issues.push(...layoutIssues.filter((issue) => issue.code === \"EXCEEDED_NESTING_DEPTH\"));\n\n    // Recursively validate nested elements\n    if (field._field === \"array\" && \"items\" in field) {\n      walkElements(\n        field.items as readonly FormElement[],\n        constraints,\n        issues,\n        `${fieldPath}[]`,\n        depth + 1\n      );\n    } else if (\"properties\" in field) {\n      // field._field === \"object\"\n      walkElements(\n        field.properties as readonly FormElement[],\n        constraints,\n        issues,\n        fieldPath,\n        depth + 1\n      );\n    }\n  }\n}\n\n/**\n * Validates a group element.\n */\nfunction validateGroup(\n  group: {\n    readonly _type: \"group\";\n    readonly label: string;\n    readonly elements: readonly FormElement[];\n  },\n  constraints: ResolvedConstraintConfig,\n  issues: ValidationIssue[],\n  pathPrefix: string,\n  depth: number\n): void {\n  const groupPath = pathPrefix ? `${pathPrefix}/[group:${group.label}]` : `[group:${group.label}]`;\n\n  // Validate group usage\n  const layoutIssues = validateLayout(\n    {\n      layoutType: \"group\",\n      label: group.label,\n      depth,\n      path: groupPath,\n    },\n    constraints.layout\n  );\n  issues.push(...layoutIssues);\n\n  // Recursively validate nested elements (groups don't increase nesting depth for schema)\n  walkElements(group.elements, constraints, issues, pathPrefix, depth);\n}\n\n/**\n * Validates a conditional element.\n */\nfunction validateConditional(\n  conditional: {\n    readonly _type: \"conditional\";\n    readonly field: string;\n    readonly value: unknown;\n    readonly elements: readonly FormElement[];\n  },\n  constraints: ResolvedConstraintConfig,\n  issues: ValidationIssue[],\n  pathPrefix: string,\n  depth: number\n): void {\n  const condPath = pathPrefix\n    ? `${pathPrefix}/[when:${conditional.field}=${String(conditional.value)}]`\n    : `[when:${conditional.field}=${String(conditional.value)}]`;\n\n  // Validate conditional usage\n  const layoutIssues = validateLayout(\n    {\n      layoutType: \"conditional\",\n      depth,\n      path: condPath,\n    },\n    constraints.layout\n  );\n  issues.push(...layoutIssues);\n\n  // Recursively validate nested elements\n  walkElements(conditional.elements, constraints, issues, pathPrefix, depth);\n}\n"],"mappings":"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","names":["severity","parseYaml"]}