//#region src/types.d.ts
/** `@platform-modules/forms` — shared contract types. Validator-agnostic (no Zod baked). */
type Result<T, E> = {
  ok: true;
  value: T;
} | {
  ok: false;
  error: E;
};
type FieldType = 'text' | 'email' | 'url' | 'tel' | 'number' | 'textarea' | 'select' | 'multiselect' | 'checkbox' | 'radio' | 'date' | 'hidden';
interface FieldDef {
  name: string;
  type: FieldType;
  label: string;
  required?: boolean;
  options?: Array<{
    value: string;
    label: string;
  }>;
  min?: number;
  max?: number;
  pattern?: string;
  default?: unknown;
}
interface ChallengeAdapter {
  verify(token: string, ctx: {
    ip?: string;
  }): Promise<boolean>;
}
interface AntiSpamConfig {
  honeypot?: string;
  minFillMs?: number;
  challenge?: ChallengeAdapter;
}
interface FormDef {
  id: string;
  fields: FieldDef[];
  antispam?: AntiSpamConfig;
  meta?: {
    name?: string;
    description?: string;
  };
}
type SubmissionValue = string | string[] | number | boolean | null;
type CleanSubmission = Record<string, SubmissionValue>;
interface StoredSubmission {
  id: string;
  formId: string;
  data: CleanSubmission;
  createdAt: string;
  meta?: {
    ip?: string;
    userAgent?: string;
    ref?: string;
  };
  spam?: boolean;
}
type FormErrorCode = 'empty-id' | 'no-fields' | 'duplicate-field' | 'missing-name' | 'missing-label' | 'no-options' | 'bad-pattern';
interface FormError {
  code: FormErrorCode;
  field?: string;
  message: string;
}
type FieldErrorCode = 'required' | 'type' | 'min' | 'max' | 'pattern' | 'option';
interface FieldError {
  field: string;
  code: FieldErrorCode;
  message: string;
}
interface AntiSpamVerdict {
  ok: boolean;
  reason?: 'honeypot' | 'too-fast' | 'bad-token' | 'challenge-failed';
}
/**
 * Structural type-guard for a {@link FieldError} — cross-package safe (no `instanceof`;
 * two deduped copies of the package would break identity-by-class).
 */
declare function isFieldError(e: unknown): e is FieldError;
//#endregion
export { FieldDef as a, FieldType as c, FormErrorCode as d, Result as f, isFieldError as h, CleanSubmission as i, FormDef as l, SubmissionValue as m, AntiSpamVerdict as n, FieldError as o, StoredSubmission as p, ChallengeAdapter as r, FieldErrorCode as s, AntiSpamConfig as t, FormError as u };