UNPKG

@matthew.ngo/react-filter-pilot

Version:

Powerful filtering, pagination, and sorting for React with TanStack Query integration

1 lines 15.3 kB
{"version":3,"sources":["../../src/hooks/useAdvancedFetchControl.ts"],"names":["useFetchControl","filters","config","debouncedFilters","useRef","debounceTimer","useEffect","shouldFetch","useMemo","filtersToCheck","filterKey","value","condition","requiredKey","key","minValue","validation","controlledFetch","useCallback","fetchFn","result","error","__name","useRequiredFilters","required","missing","useDependentFilters","dependencies","errors","dep","ifValue","requiredKeys","useFilterCombinations","rules","rule","activeFilters","isValid"],"mappings":"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","file":"useAdvancedFetchControl.cjs","sourcesContent":["import { FetchControlConfig } from '../types';\nimport { useCallback, useMemo, useRef, useEffect } from 'react';\n\n// Hook for fetch control\nexport function useFetchControl<TFilters>(\n filters: TFilters,\n config?: FetchControlConfig<TFilters>\n) {\n // Refs for debouncing\n const debouncedFilters = useRef<TFilters>(filters);\n const debounceTimer = useRef<NodeJS.Timeout | null>(null);\n\n // Update debounced filters with debounce\n // @ts-ignore\n useEffect(() => {\n if (config?.debounceMs) {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current);\n }\n\n debounceTimer.current = setTimeout(() => {\n debouncedFilters.current = filters;\n }, config.debounceMs);\n\n return () => {\n if (debounceTimer.current) {\n clearTimeout(debounceTimer.current);\n }\n };\n } else {\n debouncedFilters.current = filters;\n }\n }, [filters, config?.debounceMs]);\n\n // Check if fetch should be enabled\n const shouldFetch = useMemo(() => {\n const filtersToCheck = config?.debounceMs ? debouncedFilters.current : filters;\n if (!config) return { enabled: true, reason: '' };\n\n // Basic enabled check\n if (config.enabled !== undefined) {\n const enabled =\n typeof config.enabled === 'function' ? config.enabled(filtersToCheck) : config.enabled;\n\n if (!enabled) {\n return { enabled: false, reason: 'Fetch is disabled' };\n }\n }\n\n // Check required filters\n if (config.requiredFilters) {\n for (const filterKey of config.requiredFilters) {\n const value = filtersToCheck[filterKey];\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (Array.isArray(value) && value.length === 0)\n ) {\n return {\n enabled: false,\n reason: `Required filter \"${String(filterKey)}\" is missing`,\n };\n }\n }\n }\n\n // Check conditional requirements\n if (config.conditionalRequirements) {\n for (const condition of config.conditionalRequirements) {\n if (condition.when(filters)) {\n for (const requiredKey of condition.require) {\n const value = filters[requiredKey];\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (Array.isArray(value) && value.length === 0)\n ) {\n return {\n enabled: false,\n reason:\n condition.message ||\n `Conditional requirement not met: \"${String(requiredKey)}\" is required`,\n };\n }\n }\n }\n }\n }\n\n // Check minimum values\n if (config.minimumValues) {\n for (const [key, minValue] of Object.entries(config.minimumValues)) {\n const value = filters[key as keyof TFilters];\n if (typeof value === 'string' && value.length < (minValue as number)) {\n return {\n enabled: false,\n reason: `\"${key}\" must be at least ${minValue} characters`,\n };\n }\n if (typeof value === 'number' && value < (minValue as number)) {\n return {\n enabled: false,\n reason: `\"${key}\" must be at least ${minValue}`,\n };\n }\n }\n }\n\n // Custom validation\n if (config.validate) {\n const validation = config.validate(filters);\n if (!validation.valid) {\n return {\n enabled: false,\n reason: validation.message || 'Validation failed',\n };\n }\n }\n\n return { enabled: true, reason: '' };\n }, [filters, config]);\n\n // Wrap fetch function with control logic\n const controlledFetch = useCallback(\n async (fetchFn: () => Promise<any>) => {\n if (!shouldFetch.enabled) {\n config?.onFetchSkipped?.(shouldFetch.reason, filters);\n throw new Error(shouldFetch.reason);\n }\n\n config?.onFetchStart?.(filters);\n\n try {\n const result = await fetchFn();\n config?.onFetchEnd?.(result);\n return result;\n } catch (error) {\n config?.onFetchError?.(error as Error, filters);\n throw error;\n }\n },\n [shouldFetch, filters, config]\n );\n\n return {\n shouldFetch: shouldFetch.enabled,\n fetchReason: shouldFetch.reason,\n controlledFetch,\n };\n}\n\n// // Example: Integration with useFilterPilot\n// export function useFilterPilotWithControl<TData, TFilters = Record<string, any>>(\n// options: UseFilterPilotOptionsExtended<TData, TFilters>\n// ) {\n// const baseResult = useFilterPilot(options);\n\n// const { shouldFetch, fetchReason, controlledFetch } = useFetchControl(\n// baseResult.filters,\n// options.fetchControl\n// );\n\n// // Override the fetch config\n// const enhancedOptions = {\n// ...options,\n// fetchConfig: {\n// ...options.fetchConfig,\n// enabled: shouldFetch && options.fetchConfig.enabled !== false,\n// fetchFn: async (params: any) => {\n// return controlledFetch(() => options.fetchConfig.fetchFn(params));\n// },\n// },\n// };\n\n// // Return enhanced result\n// return {\n// ...baseResult,\n// fetchControl: {\n// isEnabled: shouldFetch,\n// reason: fetchReason,\n// retry: () => baseResult.refetch(),\n// },\n// };\n// }\n\n// Helper hooks for common patterns\nexport function useRequiredFilters<TFilters>(filters: TFilters, required: (keyof TFilters)[]) {\n return useMemo(() => {\n const missing: string[] = [];\n\n for (const key of required) {\n const value = filters[key];\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n (Array.isArray(value) && value.length === 0)\n ) {\n missing.push(String(key));\n }\n }\n\n return {\n isValid: missing.length === 0,\n missing,\n message: missing.length > 0 ? `Missing required filters: ${missing.join(', ')}` : '',\n };\n }, [filters, required]);\n}\n\n// Hook for dependent filters\nexport function useDependentFilters<TFilters>(\n filters: TFilters,\n dependencies: Array<{\n if: keyof TFilters;\n equals?: any;\n then: keyof TFilters | (keyof TFilters)[];\n }>\n) {\n return useMemo(() => {\n const errors: string[] = [];\n\n for (const dep of dependencies) {\n const ifValue = filters[dep.if];\n const shouldCheck = dep.equals !== undefined ? ifValue === dep.equals : Boolean(ifValue);\n\n if (shouldCheck) {\n const requiredKeys = Array.isArray(dep.then) ? dep.then : [dep.then];\n\n for (const key of requiredKeys) {\n const value = filters[key];\n if (!value || (Array.isArray(value) && value.length === 0)) {\n errors.push(\n `When \"${String(dep.if)}\" is set${\n dep.equals !== undefined ? ` to \"${dep.equals}\"` : ''\n }, \"${String(key)}\" is required`\n );\n }\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n }, [filters, dependencies]);\n}\n\n// Hook for filter combinations\nexport function useFilterCombinations<TFilters>(\n filters: TFilters,\n rules: Array<{\n filters: (keyof TFilters)[];\n condition: 'all' | 'any' | 'none';\n message?: string;\n }>\n) {\n return useMemo(() => {\n const errors: string[] = [];\n\n for (const rule of rules) {\n const activeFilters = rule.filters.filter((key) => {\n const value = filters[key];\n return (\n value !== undefined &&\n value !== null &&\n value !== '' &&\n !(Array.isArray(value) && value.length === 0)\n );\n });\n\n let isValid = false;\n\n switch (rule.condition) {\n case 'all':\n isValid = activeFilters.length === rule.filters.length;\n if (!isValid) {\n errors.push(\n rule.message || `All of these filters must be set: ${rule.filters.join(', ')}`\n );\n }\n break;\n\n case 'any':\n isValid = activeFilters.length > 0;\n if (!isValid) {\n errors.push(\n rule.message ||\n `At least one of these filters must be set: ${rule.filters.join(', ')}`\n );\n }\n break;\n\n case 'none':\n isValid = activeFilters.length === 0;\n if (!isValid) {\n errors.push(\n rule.message ||\n `None of these filters should be set together: ${rule.filters.join(', ')}`\n );\n }\n break;\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n };\n }, [filters, rules]);\n}\n"]}