- Adicionados ícones SVG para ChatGPT, Claude, Gemini e OpenRouter - Implementados ícones para modos claro e escuro do ChatGPT - Criado script de inicialização para PostgreSQL com extensão pgcrypto - Adicionado script de configuração de ambiente que faz backup do .env - Configurado tsconfig.json para TypeScript com opções de compilação
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];
|
|
}
|