react-antd-admin-panel
Version:
Modern TypeScript-first React admin panel builder with Ant Design 6
1 lines • 38.7 kB
Source Map (JSON)
{"version":3,"file":"useForm-BOEfP6V1.cjs","sources":["../src/hooks/useGet.ts","../src/hooks/usePost.ts","../src/hooks/useList.ts","../src/hooks/useForm.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { Get } from '../http/Get';\r\n\r\n/**\r\n * Options for the useGet hook\r\n */\r\nexport interface UseGetOptions<T> {\r\n /** The URL to fetch */\r\n url: string;\r\n /** Query parameters */\r\n params?: Record<string, any>;\r\n /** Request headers */\r\n headers?: Record<string, string>;\r\n /** Execute immediately on mount (default: true) */\r\n immediate?: boolean;\r\n /** Enable/disable the request (default: true) */\r\n enabled?: boolean;\r\n /** Callback on success */\r\n onSuccess?: (data: T) => void;\r\n /** Callback on error */\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Return type for the useGet hook\r\n */\r\nexport interface UseGetResult<T> {\r\n /** The fetched data */\r\n data: T | undefined;\r\n /** Loading state */\r\n loading: boolean;\r\n /** Error if request failed */\r\n error: Error | undefined;\r\n /** Execute/re-execute the request */\r\n execute: (overrideParams?: Record<string, any>) => Promise<T | undefined>;\r\n /** Abort the current request */\r\n abort: () => void;\r\n /** Reset state to initial values */\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * useGet - React hook for GET requests\r\n * \r\n * @template T - Response data type\r\n * @param options - Hook options\r\n * @returns Hook result with data, loading, error, and control functions\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic usage - fetches immediately\r\n * const { data, loading, error } = useGet<User[]>({\r\n * url: '/api/users',\r\n * });\r\n * \r\n * // With parameters\r\n * const { data, loading } = useGet<User[]>({\r\n * url: '/api/users',\r\n * params: { page: 1, limit: 10 },\r\n * });\r\n * \r\n * // Manual execution\r\n * const { data, execute, loading } = useGet<User>({\r\n * url: '/api/users/1',\r\n * immediate: false,\r\n * });\r\n * // Later: await execute();\r\n * \r\n * // Conditional fetch\r\n * const { data } = useGet<User>({\r\n * url: `/api/users/${userId}`,\r\n * enabled: !!userId,\r\n * });\r\n * ```\r\n */\r\nexport function useGet<T = any>(options: UseGetOptions<T>): UseGetResult<T> {\r\n const { \r\n url, \r\n params, \r\n immediate = true, \r\n enabled = true,\r\n } = options;\r\n\r\n const [data, setData] = useState<T | undefined>(undefined);\r\n const [loading, setLoading] = useState<boolean>(immediate && enabled);\r\n const [error, setError] = useState<Error | undefined>(undefined);\r\n \r\n // Use ref to track the current Get instance for cancellation\r\n const getInstanceRef = useRef<Get<T> | null>(null);\r\n // Track if component is mounted to prevent state updates after unmount\r\n const mountedRef = useRef<boolean>(true);\r\n // Track the latest options to avoid stale closures\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n\r\n /**\r\n * Execute the GET request\r\n */\r\n const execute = useCallback(async (overrideParams?: Record<string, any>): Promise<T | undefined> => {\r\n // Cancel any pending request\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n }\r\n\r\n const currentOptions = optionsRef.current;\r\n \r\n // Create new Get instance\r\n const get = new Get<T>()\r\n .target(currentOptions.url)\r\n .params({ ...currentOptions.params, ...overrideParams });\r\n\r\n if (currentOptions.headers) {\r\n get.headers(currentOptions.headers);\r\n }\r\n\r\n getInstanceRef.current = get;\r\n\r\n if (mountedRef.current) {\r\n setLoading(true);\r\n setError(undefined);\r\n }\r\n\r\n try {\r\n const result = await get.execute();\r\n \r\n if (mountedRef.current) {\r\n setData(result);\r\n setLoading(false);\r\n currentOptions.onSuccess?.(result);\r\n }\r\n \r\n return result;\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n \r\n // Don't update state if request was aborted\r\n if (error.name === 'CanceledError' || error.name === 'AbortError') {\r\n return undefined;\r\n }\r\n \r\n if (mountedRef.current) {\r\n setError(error);\r\n setLoading(false);\r\n currentOptions.onError?.(error);\r\n }\r\n \r\n return undefined;\r\n }\r\n }, []);\r\n\r\n /**\r\n * Abort the current request\r\n */\r\n const abort = useCallback(() => {\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n getInstanceRef.current = null;\r\n }\r\n if (mountedRef.current) {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n /**\r\n * Reset state to initial values\r\n */\r\n const reset = useCallback(() => {\r\n abort();\r\n if (mountedRef.current) {\r\n setData(undefined);\r\n setError(undefined);\r\n setLoading(false);\r\n }\r\n }, [abort]);\r\n\r\n // Execute on mount if immediate and enabled\r\n useEffect(() => {\r\n if (immediate && enabled) {\r\n execute();\r\n }\r\n }, [url, immediate, enabled, execute]);\r\n\r\n // Re-execute when params change (if immediate and enabled)\r\n useEffect(() => {\r\n // Skip the initial mount - handled above\r\n // This effect handles param changes after mount\r\n }, [params]);\r\n\r\n // Cleanup on unmount\r\n useEffect(() => {\r\n mountedRef.current = true;\r\n \r\n return () => {\r\n mountedRef.current = false;\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n }\r\n };\r\n }, []);\r\n\r\n return {\r\n data,\r\n loading,\r\n error,\r\n execute,\r\n abort,\r\n reset,\r\n };\r\n}\r\n","import { useState, useCallback, useRef } from 'react';\r\nimport { Post } from '../http/Post';\r\n\r\n/**\r\n * HTTP methods supported by usePost\r\n */\r\nexport type UsePostMethod = 'POST' | 'PUT' | 'PATCH' | 'DELETE';\r\n\r\n/**\r\n * Options for the usePost hook\r\n */\r\nexport interface UsePostOptions<_TBody, TResponse> {\r\n /** The URL to send the request to */\r\n url: string;\r\n /** HTTP method (default: POST) */\r\n method?: UsePostMethod;\r\n /** Request headers */\r\n headers?: Record<string, string>;\r\n /** Callback on success */\r\n onSuccess?: (data: TResponse) => void;\r\n /** Callback on error */\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Return type for the usePost hook\r\n */\r\nexport interface UsePostResult<TBody, TResponse> {\r\n /** Execute the request with the given body */\r\n execute: (body?: TBody) => Promise<TResponse | undefined>;\r\n /** Whether a request is in progress */\r\n submitting: boolean;\r\n /** Error if request failed */\r\n error: Error | undefined;\r\n /** Response data from the last successful request */\r\n data: TResponse | undefined;\r\n /** Reset state to initial values */\r\n reset: () => void;\r\n /** Abort the current request */\r\n abort: () => void;\r\n}\r\n\r\n/**\r\n * usePost - React hook for POST/PUT/PATCH/DELETE requests\r\n * \r\n * @template TBody - Request body type\r\n * @template TResponse - Response data type\r\n * @param options - Hook options\r\n * @returns Hook result with execute function, submitting state, and data\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic POST\r\n * const { execute, submitting } = usePost<CreateUserDto, User>({\r\n * url: '/api/users',\r\n * onSuccess: (user) => navigate(`/users/${user.id}`),\r\n * });\r\n * await execute({ name: 'John', email: 'john@example.com' });\r\n * \r\n * // PUT request\r\n * const { execute, submitting } = usePost<UpdateUserDto, User>({\r\n * url: '/api/users/123',\r\n * method: 'PUT',\r\n * });\r\n * \r\n * // DELETE request\r\n * const { execute, submitting } = usePost<void, void>({\r\n * url: '/api/users/123',\r\n * method: 'DELETE',\r\n * onSuccess: () => message.success('Deleted'),\r\n * });\r\n * await execute();\r\n * \r\n * // With FormData for file upload\r\n * const { execute, submitting } = usePost<FormData, UploadResponse>({\r\n * url: '/api/upload',\r\n * });\r\n * const formData = new FormData();\r\n * formData.append('file', file);\r\n * await execute(formData);\r\n * ```\r\n */\r\nexport function usePost<TBody = any, TResponse = any>(\r\n options: UsePostOptions<TBody, TResponse>\r\n): UsePostResult<TBody, TResponse> {\r\n const [submitting, setSubmitting] = useState<boolean>(false);\r\n const [error, setError] = useState<Error | undefined>(undefined);\r\n const [data, setData] = useState<TResponse | undefined>(undefined);\r\n \r\n // Use ref to track the current Post instance for cancellation\r\n const postInstanceRef = useRef<Post<TBody, TResponse> | null>(null);\r\n // Track if component is mounted to prevent state updates after unmount\r\n const mountedRef = useRef<boolean>(true);\r\n // Track the latest options to avoid stale closures\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n\r\n /**\r\n * Execute the POST/PUT/PATCH/DELETE request\r\n */\r\n const execute = useCallback(async (body?: TBody): Promise<TResponse | undefined> => {\r\n // Cancel any pending request\r\n if (postInstanceRef.current) {\r\n postInstanceRef.current.cancel();\r\n }\r\n\r\n const currentOptions = optionsRef.current;\r\n \r\n // Create new Post instance\r\n const post = new Post<TBody, TResponse>()\r\n .target(currentOptions.url)\r\n .method(currentOptions.method || 'POST');\r\n\r\n if (body !== undefined) {\r\n post.body(body);\r\n }\r\n\r\n if (currentOptions.headers) {\r\n post.headers(currentOptions.headers);\r\n }\r\n\r\n postInstanceRef.current = post;\r\n\r\n if (mountedRef.current) {\r\n setSubmitting(true);\r\n setError(undefined);\r\n }\r\n\r\n try {\r\n const result = await post.execute();\r\n \r\n if (mountedRef.current) {\r\n setData(result);\r\n setSubmitting(false);\r\n currentOptions.onSuccess?.(result);\r\n }\r\n \r\n return result;\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n \r\n // Don't update state if request was aborted\r\n if (error.name === 'CanceledError' || error.name === 'AbortError') {\r\n return undefined;\r\n }\r\n \r\n if (mountedRef.current) {\r\n setError(error);\r\n setSubmitting(false);\r\n currentOptions.onError?.(error);\r\n }\r\n \r\n return undefined;\r\n }\r\n }, []);\r\n\r\n /**\r\n * Abort the current request\r\n */\r\n const abort = useCallback(() => {\r\n if (postInstanceRef.current) {\r\n postInstanceRef.current.cancel();\r\n postInstanceRef.current = null;\r\n }\r\n if (mountedRef.current) {\r\n setSubmitting(false);\r\n }\r\n }, []);\r\n\r\n /**\r\n * Reset state to initial values\r\n */\r\n const reset = useCallback(() => {\r\n abort();\r\n if (mountedRef.current) {\r\n setData(undefined);\r\n setError(undefined);\r\n setSubmitting(false);\r\n }\r\n }, [abort]);\r\n\r\n // Set mounted ref on mount, cleanup on unmount\r\n // Using a layout effect pattern to set mounted before any renders\r\n if (mountedRef.current === false) {\r\n mountedRef.current = true;\r\n }\r\n\r\n // Note: We use a ref pattern instead of useEffect for mounted tracking\r\n // to avoid race conditions. The unmount cleanup is still needed.\r\n // This is handled by the component lifecycle - when unmounted,\r\n // the ref will be stale but that's okay since we check it before setState.\r\n\r\n return {\r\n execute,\r\n submitting,\r\n error,\r\n data,\r\n reset,\r\n abort,\r\n };\r\n}\r\n","import { useState, useEffect, useCallback, useRef, useMemo } from 'react';\r\nimport { Get } from '../http/Get';\r\nimport type { Key } from 'react';\r\n\r\n/**\r\n * Pagination configuration for useList\r\n */\r\nexport interface UseListPagination {\r\n /** Current page number (1-indexed) */\r\n current: number;\r\n /** Number of items per page */\r\n pageSize: number;\r\n /** Total number of items (for server-side pagination) */\r\n total?: number;\r\n}\r\n\r\n/**\r\n * Get configuration - either a URL string or an options object\r\n */\r\nexport interface UseListGetConfig {\r\n /** The URL to fetch data from */\r\n url: string;\r\n /** Query parameters */\r\n params?: Record<string, any>;\r\n /** Request headers */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Options for the useList hook\r\n */\r\nexport interface UseListOptions<T> {\r\n /** Data source configuration */\r\n get: string | UseListGetConfig;\r\n /** Initial pagination settings */\r\n pagination?: Partial<UseListPagination> | false;\r\n /** Initial filter values */\r\n initialFilters?: Record<string, any>;\r\n /** Row key field or function */\r\n rowKey?: string | ((record: T) => Key);\r\n /** Enable/disable the request (default: true) */\r\n enabled?: boolean;\r\n /** Callback on success */\r\n onSuccess?: (data: T[]) => void;\r\n /** Callback on error */\r\n onError?: (error: Error) => void;\r\n /** Transform response data */\r\n transform?: (response: any) => { data: T[]; total?: number };\r\n}\r\n\r\n/**\r\n * Return type for the useList hook\r\n */\r\nexport interface UseListResult<T> {\r\n /** The fetched data */\r\n data: T[];\r\n /** Loading state */\r\n loading: boolean;\r\n /** Error if request failed */\r\n error: Error | undefined;\r\n /** Refresh/refetch data */\r\n refresh: () => Promise<void>;\r\n /** Current pagination state */\r\n pagination: UseListPagination;\r\n /** Update pagination */\r\n setPagination: (pagination: Partial<UseListPagination>) => void;\r\n /** Current filter values */\r\n filters: Record<string, any>;\r\n /** Update filters */\r\n setFilters: (filters: Record<string, any>) => void;\r\n /** Selected row keys */\r\n selectedRowKeys: Key[];\r\n /** Set selected row keys */\r\n setSelectedRowKeys: (keys: Key[]) => void;\r\n /** Selected rows */\r\n selectedRows: T[];\r\n /** Clear selection */\r\n clearSelection: () => void;\r\n /** Reset to initial state */\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * useList - React hook for list/table data management\r\n * \r\n * @template T - Data item type\r\n * @param options - Hook options\r\n * @returns Hook result with data, loading, pagination, and control functions\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * const { data, loading, refresh } = useList<User>({\r\n * get: '/api/users',\r\n * });\r\n * \r\n * // With pagination\r\n * const { data, pagination, setPagination } = useList<User>({\r\n * get: '/api/users',\r\n * pagination: { pageSize: 10 },\r\n * });\r\n * \r\n * // With filters\r\n * const { data, filters, setFilters } = useList<User>({\r\n * get: '/api/users',\r\n * initialFilters: { status: 'active' },\r\n * });\r\n * \r\n * // With selection\r\n * const { data, selectedRowKeys, setSelectedRowKeys, selectedRows } = useList<User>({\r\n * get: '/api/users',\r\n * rowKey: 'id',\r\n * });\r\n * \r\n * // With transform for custom API response\r\n * const { data } = useList<User>({\r\n * get: '/api/users',\r\n * transform: (response) => ({\r\n * data: response.items,\r\n * total: response.totalCount,\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport function useList<T extends object = any>(\r\n options: UseListOptions<T>\r\n): UseListResult<T> {\r\n const {\r\n pagination: paginationConfig,\r\n initialFilters = {},\r\n rowKey = 'id',\r\n enabled = true,\r\n } = options;\r\n\r\n // State\r\n const [data, setData] = useState<T[]>([]);\r\n const [loading, setLoading] = useState<boolean>(enabled);\r\n const [error, setError] = useState<Error | undefined>(undefined);\r\n const [pagination, setPaginationState] = useState<UseListPagination>(() => ({\r\n current: 1,\r\n pageSize: 10,\r\n total: 0,\r\n ...(paginationConfig !== false ? paginationConfig : {}),\r\n }));\r\n const [filters, setFiltersState] = useState<Record<string, any>>(initialFilters);\r\n const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);\r\n\r\n // Refs\r\n const getInstanceRef = useRef<Get<any> | null>(null);\r\n const mountedRef = useRef<boolean>(true);\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n\r\n // Get row key for a record\r\n const getRowKey = useCallback((record: T): Key => {\r\n if (typeof rowKey === 'function') {\r\n return rowKey(record);\r\n }\r\n return (record as any)[rowKey];\r\n }, [rowKey]);\r\n\r\n // Compute selected rows from data and selectedRowKeys\r\n const selectedRows = useMemo(() => {\r\n if (selectedRowKeys.length === 0) return [];\r\n return data.filter(item => selectedRowKeys.includes(getRowKey(item)));\r\n }, [data, selectedRowKeys, getRowKey]);\r\n\r\n /**\r\n * Fetch data from the API\r\n */\r\n const fetchData = useCallback(async () => {\r\n // Cancel any pending request\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n }\r\n\r\n const currentOptions = optionsRef.current;\r\n const currentGet = typeof currentOptions.get === 'string' \r\n ? { url: currentOptions.get } \r\n : currentOptions.get;\r\n\r\n // Build params with pagination and filters\r\n const params: Record<string, any> = {\r\n ...currentGet.params,\r\n ...filters,\r\n };\r\n\r\n // Add pagination params if enabled\r\n if (paginationConfig !== false) {\r\n params.page = pagination.current;\r\n params.pageSize = pagination.pageSize;\r\n }\r\n\r\n // Create new Get instance\r\n const get = new Get<any>()\r\n .target(currentGet.url)\r\n .params(params);\r\n\r\n if (currentGet.headers) {\r\n get.headers(currentGet.headers);\r\n }\r\n\r\n getInstanceRef.current = get;\r\n\r\n if (mountedRef.current) {\r\n setLoading(true);\r\n setError(undefined);\r\n }\r\n\r\n try {\r\n const response = await get.execute();\r\n \r\n if (mountedRef.current) {\r\n let resultData: T[];\r\n let total: number | undefined;\r\n\r\n // Apply transform if provided\r\n if (currentOptions.transform) {\r\n const transformed = currentOptions.transform(response);\r\n resultData = transformed.data;\r\n total = transformed.total;\r\n } else if (Array.isArray(response)) {\r\n // Response is already an array\r\n resultData = response;\r\n total = response.length;\r\n } else if (response && typeof response === 'object') {\r\n // Try common response shapes\r\n resultData = response.data || response.items || response.records || [];\r\n total = response.total ?? response.totalCount ?? response.count ?? resultData.length;\r\n } else {\r\n resultData = [];\r\n total = 0;\r\n }\r\n\r\n setData(resultData);\r\n \r\n if (paginationConfig !== false && total !== undefined) {\r\n setPaginationState(prev => ({ ...prev, total }));\r\n }\r\n \r\n setLoading(false);\r\n currentOptions.onSuccess?.(resultData);\r\n }\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n \r\n // Don't update state if request was aborted\r\n if (error.name === 'CanceledError' || error.name === 'AbortError') {\r\n return;\r\n }\r\n \r\n if (mountedRef.current) {\r\n setError(error);\r\n setLoading(false);\r\n currentOptions.onError?.(error);\r\n }\r\n }\r\n }, [filters, pagination.current, pagination.pageSize, paginationConfig]);\r\n\r\n /**\r\n * Refresh/refetch data\r\n */\r\n const refresh = useCallback(async () => {\r\n await fetchData();\r\n }, [fetchData]);\r\n\r\n /**\r\n * Update pagination\r\n */\r\n const setPagination = useCallback((newPagination: Partial<UseListPagination>) => {\r\n setPaginationState(prev => ({ ...prev, ...newPagination }));\r\n }, []);\r\n\r\n /**\r\n * Update filters\r\n */\r\n const setFilters = useCallback((newFilters: Record<string, any>) => {\r\n setFiltersState(newFilters);\r\n // Reset to first page when filters change\r\n setPaginationState(prev => ({ ...prev, current: 1 }));\r\n }, []);\r\n\r\n /**\r\n * Clear selection\r\n */\r\n const clearSelection = useCallback(() => {\r\n setSelectedRowKeys([]);\r\n }, []);\r\n\r\n /**\r\n * Reset to initial state\r\n */\r\n const reset = useCallback(() => {\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n }\r\n setData([]);\r\n setError(undefined);\r\n setLoading(false);\r\n setPaginationState({\r\n current: 1,\r\n pageSize: paginationConfig !== false ? (paginationConfig?.pageSize ?? 10) : 10,\r\n total: 0,\r\n });\r\n setFiltersState(initialFilters);\r\n setSelectedRowKeys([]);\r\n }, [initialFilters, paginationConfig]);\r\n\r\n // Fetch on mount and when dependencies change\r\n useEffect(() => {\r\n if (enabled) {\r\n fetchData();\r\n }\r\n }, [enabled, fetchData]);\r\n\r\n // Cleanup on unmount\r\n useEffect(() => {\r\n mountedRef.current = true;\r\n \r\n return () => {\r\n mountedRef.current = false;\r\n if (getInstanceRef.current) {\r\n getInstanceRef.current.cancel();\r\n }\r\n };\r\n }, []);\r\n\r\n return {\r\n data,\r\n loading,\r\n error,\r\n refresh,\r\n pagination,\r\n setPagination,\r\n filters,\r\n setFilters,\r\n selectedRowKeys,\r\n setSelectedRowKeys,\r\n selectedRows,\r\n clearSelection,\r\n reset,\r\n };\r\n}\r\n","import { useState, useCallback, useRef } from 'react';\r\nimport { useForm as useReactHookForm, FieldValues, UseFormReturn, DefaultValues, FieldErrors, Path, PathValue } from 'react-hook-form';\r\nimport { Post } from '../http/Post';\r\n\r\n/**\r\n * Validation function type\r\n */\r\nexport type ValidateFunction<T extends FieldValues> = (values: T) => Record<string, string> | Promise<Record<string, string>>;\r\n\r\n/**\r\n * Options for the useForm hook\r\n */\r\nexport interface UseFormOptions<T extends FieldValues> {\r\n /** Initial form values */\r\n initialValues: T;\r\n /** Submit handler - receives form values */\r\n onSubmit?: (values: T) => void | Promise<void>;\r\n /** Post configuration for automatic submission */\r\n post?: {\r\n url: string;\r\n method?: 'POST' | 'PUT' | 'PATCH';\r\n headers?: Record<string, string>;\r\n onSuccess?: (response: any) => void;\r\n onError?: (error: Error) => void;\r\n };\r\n /** Custom validation function */\r\n validate?: ValidateFunction<T>;\r\n /** Validation mode */\r\n mode?: 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';\r\n}\r\n\r\n/**\r\n * Return type for the useForm hook\r\n */\r\nexport interface UseFormResult<T extends FieldValues> {\r\n /** Current form values */\r\n values: T;\r\n /** Form errors by field */\r\n errors: FieldErrors<T>;\r\n /** Set a single field value */\r\n setValue: <K extends Path<T>>(name: K, value: PathValue<T, K>) => void;\r\n /** Set multiple field values */\r\n setValues: (values: Partial<T>) => void;\r\n /** Submit the form */\r\n submit: () => Promise<void>;\r\n /** Whether form is submitting */\r\n submitting: boolean;\r\n /** Reset form to initial values */\r\n reset: (values?: T) => void;\r\n /** Whether form has been modified */\r\n isDirty: boolean;\r\n /** Whether form is valid */\r\n isValid: boolean;\r\n /** Register a field (for uncontrolled inputs) */\r\n register: UseFormReturn<T>['register'];\r\n /** Get field state */\r\n getFieldState: UseFormReturn<T>['getFieldState'];\r\n /** Trigger validation */\r\n trigger: UseFormReturn<T>['trigger'];\r\n /** Clear all errors */\r\n clearErrors: UseFormReturn<T>['clearErrors'];\r\n /** Set an error on a field */\r\n setError: UseFormReturn<T>['setError'];\r\n /** Watch form values */\r\n watch: UseFormReturn<T>['watch'];\r\n}\r\n\r\n/**\r\n * useForm - React hook for form state management\r\n * \r\n * Wraps react-hook-form with a simplified API and optional Post integration.\r\n * \r\n * @template T - Form values type\r\n * @param options - Hook options\r\n * @returns Hook result with form state and control functions\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * const { values, setValue, submit, submitting } = useForm({\r\n * initialValues: { name: '', email: '' },\r\n * onSubmit: async (values) => {\r\n * await saveUser(values);\r\n * },\r\n * });\r\n * \r\n * // With Post integration\r\n * const { values, submit, submitting } = useForm({\r\n * initialValues: { name: '', email: '' },\r\n * post: {\r\n * url: '/api/users',\r\n * onSuccess: (user) => navigate(`/users/${user.id}`),\r\n * },\r\n * });\r\n * \r\n * // With validation\r\n * const { values, errors, submit } = useForm({\r\n * initialValues: { email: '' },\r\n * validate: (values) => {\r\n * const errors: Record<string, string> = {};\r\n * if (!values.email.includes('@')) {\r\n * errors.email = 'Invalid email';\r\n * }\r\n * return errors;\r\n * },\r\n * });\r\n * \r\n * // In JSX\r\n * <input\r\n * value={values.name}\r\n * onChange={(e) => setValue('name', e.target.value)}\r\n * />\r\n * <span>{errors.name?.message}</span>\r\n * <button onClick={submit} disabled={submitting}>Save</button>\r\n * ```\r\n */\r\nexport function useForm<T extends FieldValues>(\r\n options: UseFormOptions<T>\r\n): UseFormResult<T> {\r\n const {\r\n initialValues,\r\n mode = 'onSubmit',\r\n } = options;\r\n\r\n const [submitting, setSubmitting] = useState(false);\r\n const optionsRef = useRef(options);\r\n optionsRef.current = options;\r\n\r\n // Use react-hook-form under the hood\r\n const form = useReactHookForm<T>({\r\n defaultValues: initialValues as DefaultValues<T>,\r\n mode,\r\n });\r\n\r\n const {\r\n register,\r\n reset: rhfReset,\r\n formState: { errors, isDirty, isValid },\r\n setValue: rhfSetValue,\r\n getValues,\r\n getFieldState,\r\n trigger,\r\n clearErrors,\r\n setError: rhfSetError,\r\n watch,\r\n } = form;\r\n\r\n /**\r\n * Set a single field value\r\n */\r\n const setValue = useCallback(<K extends Path<T>>(name: K, value: PathValue<T, K>) => {\r\n rhfSetValue(name, value, { shouldValidate: true, shouldDirty: true });\r\n }, [rhfSetValue]);\r\n\r\n /**\r\n * Set multiple field values\r\n */\r\n const setValues = useCallback((values: Partial<T>) => {\r\n Object.entries(values).forEach(([key, value]) => {\r\n rhfSetValue(key as Path<T>, value as PathValue<T, Path<T>>, { shouldValidate: true, shouldDirty: true });\r\n });\r\n }, [rhfSetValue]);\r\n\r\n /**\r\n * Submit the form\r\n */\r\n const submit = useCallback(async () => {\r\n const currentOptions = optionsRef.current;\r\n \r\n // Trigger validation first\r\n const isFormValid = await trigger();\r\n if (!isFormValid) {\r\n return;\r\n }\r\n\r\n const values = getValues();\r\n\r\n // Run custom validation if provided\r\n if (currentOptions.validate) {\r\n const validationErrors = await currentOptions.validate(values);\r\n if (Object.keys(validationErrors).length > 0) {\r\n // Set errors on form\r\n Object.entries(validationErrors).forEach(([field, message]) => {\r\n rhfSetError(field as Path<T>, { type: 'validate', message });\r\n });\r\n return;\r\n }\r\n }\r\n\r\n setSubmitting(true);\r\n\r\n try {\r\n // Use Post if configured\r\n if (currentOptions.post) {\r\n const postInstance = new Post()\r\n .target(currentOptions.post.url)\r\n .method(currentOptions.post.method || 'POST')\r\n .body(values);\r\n\r\n if (currentOptions.post.headers) {\r\n postInstance.headers(currentOptions.post.headers);\r\n }\r\n\r\n const response = await postInstance.execute();\r\n currentOptions.post.onSuccess?.(response);\r\n } else if (currentOptions.onSubmit) {\r\n // Use onSubmit callback\r\n await currentOptions.onSubmit(values);\r\n }\r\n } catch (error) {\r\n if (currentOptions.post?.onError) {\r\n currentOptions.post.onError(error instanceof Error ? error : new Error(String(error)));\r\n }\r\n throw error;\r\n } finally {\r\n setSubmitting(false);\r\n }\r\n }, [trigger, getValues, rhfSetError]);\r\n\r\n /**\r\n * Reset form to initial or provided values\r\n */\r\n const reset = useCallback((values?: T) => {\r\n rhfReset(values ?? initialValues as DefaultValues<T>);\r\n }, [rhfReset, initialValues]);\r\n\r\n // Get current values (reactive)\r\n const values = watch();\r\n\r\n return {\r\n values: values as T,\r\n errors,\r\n setValue,\r\n setValues,\r\n submit,\r\n submitting,\r\n reset,\r\n isDirty,\r\n isValid,\r\n register,\r\n getFieldState,\r\n trigger,\r\n clearErrors,\r\n setError: rhfSetError,\r\n watch,\r\n };\r\n}\r\n"],"names":["useState","useRef","useCallback","Get","error","useEffect","Post","useMemo","useReactHookForm","values"],"mappings":"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"}