forked from git.gladyson/openmonetis
- Replace ESLint with Biome for linting and formatting - Configure Biome with tabs, double quotes, and organized imports - Move all SQL/Drizzle queries from page.tsx files to data.ts files - Create new data.ts files for: ajustes, dashboard, relatorios/categorias - Update existing data.ts files: extrato, fatura (add lancamentos queries) - Remove all drizzle-orm imports from page.tsx files - Update README.md with new tooling info Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
|
|
/**
|
|
* Hook for managing controlled/uncontrolled state pattern
|
|
* Allows a component to work both in controlled and uncontrolled mode
|
|
*
|
|
* @param controlledValue - The controlled value (undefined for uncontrolled mode)
|
|
* @param defaultValue - Default value for uncontrolled mode
|
|
* @param onChange - Callback when value changes
|
|
* @returns Tuple of [currentValue, setValue]
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* function MyComponent({ value, onChange }) {
|
|
* const [internalValue, setValue] = useControlledState(value, false, onChange);
|
|
* // Works both as controlled and uncontrolled
|
|
* }
|
|
* ```
|
|
*/
|
|
export function useControlledState<T>(
|
|
controlledValue: T | undefined,
|
|
defaultValue: T,
|
|
onChange?: (value: T) => void,
|
|
): [T, (value: T) => void] {
|
|
const [internalValue, setInternalValue] = useState<T>(defaultValue);
|
|
|
|
// Sync internal value when controlled value changes
|
|
useEffect(() => {
|
|
if (controlledValue !== undefined) {
|
|
setInternalValue(controlledValue);
|
|
}
|
|
}, [controlledValue]);
|
|
|
|
// Use controlled value if provided, otherwise use internal value
|
|
const value = controlledValue !== undefined ? controlledValue : internalValue;
|
|
|
|
const setValue = useCallback(
|
|
(newValue: T) => {
|
|
// Update internal state if uncontrolled
|
|
if (controlledValue === undefined) {
|
|
setInternalValue(newValue);
|
|
}
|
|
|
|
// Always call onChange if provided
|
|
onChange?.(newValue);
|
|
},
|
|
[controlledValue, onChange],
|
|
);
|
|
|
|
return [value, setValue];
|
|
}
|