import type { FieldNode, RecordField, VariantField, TupleField, OptionalField, VectorField, BlobField, RecursiveField, PrincipalField, NumberField, BooleanField, NullField, TextField, UnknownField, ArgumentsMeta, ArgumentsServiceMeta } from "./types.js"; import { IDL } from "@icp-sdk/core/candid"; import { BaseActor, FunctionName } from "@ic-reactor/core"; import * as z from "zod"; export * from "./types.js"; export * from "./helpers.js"; export { checkTextFormat, checkNumberFormat } from "../constants.js"; /** * FieldVisitor generates metadata for form input fields from Candid IDL types. * * ## Design Principles * * 1. **Works with raw IDL types** - generates metadata at initialization time * 2. **No value dependencies** - metadata is independent of actual values * 3. **Form-framework agnostic** - output can be used with TanStack, React Hook Form, etc. * 4. **Efficient** - single traversal, no runtime type checking * 5. **TanStack Form optimized** - name paths compatible with TanStack Form patterns * * ## Output Structure * * Each field has: * - `type`: The field type (record, variant, text, number, etc.) * - `label`: Raw label from Candid * - `displayLabel`: Human-readable formatted label * - `name`: TanStack Form compatible path (e.g., "[0]", "[0].owner", "tags[1]") * - `component`: Suggested component type for rendering * - `renderHint`: Hints for UI rendering strategy * - `defaultValue`: Initial value for the form * - `schema`: Zod schema for validation * - Type-specific properties (options for variant, fields for record, etc.) * - Helper methods for dynamic forms (getOptionDefault, getItemDefault, etc.) * * ## Usage with TanStack Form * * @example * ```typescript * import { useForm } from '@tanstack/react-form' * import { FieldVisitor } from '@ic-reactor/candid' * * const visitor = new FieldVisitor() * const serviceMeta = service.accept(visitor, null) * const methodMeta = serviceMeta["icrc1_transfer"] * * const form = useForm({ * defaultValues: methodMeta.defaultValue, * validators: { onBlur: methodMeta.schema }, * onSubmit: async ({ value }) => { * await actor.icrc1_transfer(...value) * } * }) * * // Render fields dynamically * methodMeta.fields.map((field, index) => ( *