{"$schema":"https:\/\/ui.particle.academy\/schema\/registry-item.json","name":"use-fancy-form","type":"registry:ui","title":"useFancyForm","description":"Form hook.","package":"fancy-inertia","dependencies":["@inertiajs\/react"],"registryDependencies":[],"files":[{"path":"components\/fancy\/use-fancy-form\/useFancyForm.ts","content":"import { useCallback, useMemo } from \"react\";\r\nimport { useForm as inertiaUseForm } from \"@inertiajs\/react\";\r\n\r\n\/**\r\n * Per-field bridge returned by `useFancyForm().field(name)`. Shaped to\r\n * drop directly into react-fancy form components without further\r\n * wiring.\r\n *\/\r\nexport interface FancyFieldBridge<T = unknown> {\r\n  \/** Pass to `<Input value={...} \/>` \u2014 current field value (string). *\/\r\n  value: T;\r\n  \/** Pass to `<Input onChange={...} \/>`. Accepts the React event *or* a raw value (Select, Switch). *\/\r\n  onChange: (e: React.ChangeEvent<HTMLInputElement> | T) => void;\r\n  \/** Pass to `<Input error={...} \/>` \u2014 last server validation error for this field. *\/\r\n  error?: string;\r\n  \/** True while a submit is in flight. *\/\r\n  loading?: boolean;\r\n  \/** Stable name attribute. *\/\r\n  name: string;\r\n}\r\n\r\n\/**\r\n * Bridge type returned by useFancyForm. Wraps Inertia's `useForm()` and\r\n * adds a `field(name)` helper that returns props ready to spread into\r\n * react-fancy's `<Input>`, `<Select>`, `<Switch>`, `<Textarea>`, etc.\r\n *\/\r\nexport interface FancyFormBridge<TData extends Record<string, unknown>> {\r\n  data: TData;\r\n  setData: <K extends keyof TData>(key: K, value: TData[K]) => void;\r\n  errors: Partial<Record<keyof TData, string>>;\r\n  processing: boolean;\r\n\r\n  \/**\r\n   * Returns `{ value, onChange, error, loading, name }` for a field.\r\n   * `onChange` accepts both a React change event (native input\/textarea)\r\n   * and a raw value (Select\/Switch\/MultiSwitch which pass the new value\r\n   * directly).\r\n   *\/\r\n  field<K extends keyof TData & string>(name: K): FancyFieldBridge<TData[K]>;\r\n\r\n  \/** Forwarded from Inertia's useForm. *\/\r\n  submit: (method: string, url: string, options?: object) => void;\r\n  post: (url: string, options?: object) => void;\r\n  put: (url: string, options?: object) => void;\r\n  patch: (url: string, options?: object) => void;\r\n  delete: (url: string, options?: object) => void;\r\n  reset: (...fields: Array<keyof TData>) => void;\r\n  clearErrors: (...fields: Array<keyof TData>) => void;\r\n}\r\n\r\n\/**\r\n * Inertia's `useForm()` shape (loose typing \u2014 we don't import @inertiajs\r\n * statically since it's an optional peer when fancy-inertia is used\r\n * outside of Inertia for code-sharing reasons).\r\n *\/\r\ntype InertiaForm<T> = {\r\n  data: T;\r\n  setData: (key: keyof T, value: unknown) => void;\r\n  errors: Partial<Record<keyof T, string>>;\r\n  processing: boolean;\r\n  submit: (method: string, url: string, options?: object) => void;\r\n  post: (url: string, options?: object) => void;\r\n  put: (url: string, options?: object) => void;\r\n  patch: (url: string, options?: object) => void;\r\n  delete: (url: string, options?: object) => void;\r\n  reset: (...fields: Array<keyof T>) => void;\r\n  clearErrors: (...fields: Array<keyof T>) => void;\r\n};\r\n\r\n\/**\r\n * Wraps Inertia's `useForm()` so each field can be wired into react-fancy\r\n * inputs in one line:\r\n *\r\n *   const form = useFancyForm({ name: \"\", email: \"\" });\r\n *   <Input {...form.field(\"name\")} placeholder=\"Name\" \/>\r\n *   <Input {...form.field(\"email\")} placeholder=\"Email\" \/>\r\n *   <Button onClick={() => form.post(\"\/users\")}>Save<\/Button>\r\n *\r\n * Call signature mirrors `useForm()` from @inertiajs\/react. Pass either\r\n * the initial values, or the result of `useForm(...)` if you've already\r\n * called it (lets you compose with library-supplied form objects):\r\n *\r\n *   const inertiaForm = useForm({ name: \"\" });\r\n *   const form = useFancyForm(inertiaForm);\r\n *\/\r\nexport function useFancyForm<TData extends Record<string, unknown>>(\r\n  initialOrForm: TData | InertiaForm<TData>,\r\n): FancyFormBridge<TData> {\r\n  \/\/ Lazy-resolve @inertiajs\/react. If the consumer has already called\r\n  \/\/ useForm() and passed the result in, we re-use it directly. Otherwise\r\n  \/\/ we instantiate via the package.\r\n  const form = useMemo<InertiaForm<TData>>(() => {\r\n    if (isInertiaForm<TData>(initialOrForm)) {\r\n      return initialOrForm;\r\n    }\r\n    return useInertiaFormShim(initialOrForm) as InertiaForm<TData>;\r\n    \/\/ eslint-disable-next-line react-hooks\/exhaustive-deps\r\n  }, [initialOrForm]);\r\n\r\n  const field = useCallback(\r\n    <K extends keyof TData & string>(name: K): FancyFieldBridge<TData[K]> => ({\r\n      name,\r\n      value: form.data[name],\r\n      onChange: (e) => {\r\n        const next =\r\n          e !== null && typeof e === \"object\" && \"target\" in (e as object)\r\n            ? ((e as React.ChangeEvent<HTMLInputElement>).target as HTMLInputElement & {\r\n                checked?: boolean;\r\n                type?: string;\r\n              })\r\n            : null;\r\n        if (next) {\r\n          const value = next.type === \"checkbox\" ? next.checked : next.value;\r\n          form.setData(name, value as unknown as TData[K]);\r\n        } else {\r\n          form.setData(name, e as unknown as TData[K]);\r\n        }\r\n      },\r\n      error: form.errors[name],\r\n      loading: form.processing,\r\n    }),\r\n    [form],\r\n  );\r\n\r\n  return {\r\n    data: form.data,\r\n    setData: form.setData as FancyFormBridge<TData>[\"setData\"],\r\n    errors: form.errors,\r\n    processing: form.processing,\r\n    field,\r\n    submit: form.submit,\r\n    post: form.post,\r\n    put: form.put,\r\n    patch: form.patch,\r\n    delete: form.delete,\r\n    reset: form.reset,\r\n    clearErrors: form.clearErrors,\r\n  };\r\n}\r\n\r\nfunction isInertiaForm<T>(x: unknown): x is InertiaForm<T> {\r\n  return (\r\n    typeof x === \"object\" &&\r\n    x !== null &&\r\n    \"data\" in (x as object) &&\r\n    \"setData\" in (x as object) &&\r\n    \"errors\" in (x as object) &&\r\n    \"processing\" in (x as object)\r\n  );\r\n}\r\n\r\nfunction useInertiaFormShim<TData extends Record<string, unknown>>(initial: TData): InertiaForm<TData> {\r\n  return inertiaUseForm(initial as any) as unknown as InertiaForm<TData>;\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/use-fancy-form\/useFancyForm.ts"}]}