'use client'; import { useState, useEffect, useRef } from 'react'; import { Slider } from '@/components/ui/slider'; import { Button } from '@/components/ui/button'; import { useLighten, useDarken, useSaturate, useDesaturate, useRotate, useComplement } from '@/lib/api/queries'; import { toast } from 'sonner'; interface ManipulationPanelProps { color: string; onColorChange: (color: string) => void; } export function ManipulationPanel({ color, onColorChange }: ManipulationPanelProps) { const [lightenAmount, setLightenAmount] = useState(0.2); const [darkenAmount, setDarkenAmount] = useState(0.2); const [saturateAmount, setSaturateAmount] = useState(0.2); const [desaturateAmount, setDesaturateAmount] = useState(0.2); const [rotateAmount, setRotateAmount] = useState(30); const lightenMutation = useLighten(); const darkenMutation = useDarken(); const saturateMutation = useSaturate(); const desaturateMutation = useDesaturate(); const rotateMutation = useRotate(); const complementMutation = useComplement(); // Debounce timers const lightenTimer = useRef(undefined); const darkenTimer = useRef(undefined); const saturateTimer = useRef(undefined); const desaturateTimer = useRef(undefined); const rotateTimer = useRef(undefined); // Reactive lighten useEffect(() => { if (lightenTimer.current) clearTimeout(lightenTimer.current); lightenTimer.current = setTimeout(async () => { if (lightenAmount > 0) { try { const result = await lightenMutation.mutateAsync({ colors: [color], amount: lightenAmount, }); if (result.colors[0]) { onColorChange(result.colors[0].output); } } catch (error) { // Silent error - user is still adjusting } } }, 300); }, [lightenAmount]); // Reactive darken useEffect(() => { if (darkenTimer.current) clearTimeout(darkenTimer.current); darkenTimer.current = setTimeout(async () => { if (darkenAmount > 0) { try { const result = await darkenMutation.mutateAsync({ colors: [color], amount: darkenAmount, }); if (result.colors[0]) { onColorChange(result.colors[0].output); } } catch (error) { // Silent error - user is still adjusting } } }, 300); }, [darkenAmount]); // Reactive saturate useEffect(() => { if (saturateTimer.current) clearTimeout(saturateTimer.current); saturateTimer.current = setTimeout(async () => { if (saturateAmount > 0) { try { const result = await saturateMutation.mutateAsync({ colors: [color], amount: saturateAmount, }); if (result.colors[0]) { onColorChange(result.colors[0].output); } } catch (error) { // Silent error - user is still adjusting } } }, 300); }, [saturateAmount]); // Reactive desaturate useEffect(() => { if (desaturateTimer.current) clearTimeout(desaturateTimer.current); desaturateTimer.current = setTimeout(async () => { if (desaturateAmount > 0) { try { const result = await desaturateMutation.mutateAsync({ colors: [color], amount: desaturateAmount, }); if (result.colors[0]) { onColorChange(result.colors[0].output); } } catch (error) { // Silent error - user is still adjusting } } }, 300); }, [desaturateAmount]); // Reactive rotate useEffect(() => { if (rotateTimer.current) clearTimeout(rotateTimer.current); rotateTimer.current = setTimeout(async () => { if (rotateAmount !== 0) { try { const result = await rotateMutation.mutateAsync({ colors: [color], amount: rotateAmount, }); if (result.colors[0]) { onColorChange(result.colors[0].output); } } catch (error) { // Silent error - user is still adjusting } } }, 300); }, [rotateAmount]); const handleComplement = async () => { try { const result = await complementMutation.mutateAsync([color]); if (result.colors[0]) { onColorChange(result.colors[0].output); toast.success('Generated complementary color'); } } catch (error) { toast.error('Failed to generate complement'); } }; const isLoading = lightenMutation.isPending || darkenMutation.isPending || saturateMutation.isPending || desaturateMutation.isPending || rotateMutation.isPending || complementMutation.isPending; return (
{/* Lighten */}
setLightenAmount(parseFloat(e.target.value))} suffix="%" showValue />
{/* Darken */}
setDarkenAmount(parseFloat(e.target.value))} suffix="%" showValue />
{/* Saturate */}
setSaturateAmount(parseFloat(e.target.value))} suffix="%" showValue />
{/* Desaturate */}
setDesaturateAmount(parseFloat(e.target.value))} suffix="%" showValue />
{/* Rotate Hue */}
setRotateAmount(parseInt(e.target.value))} suffix="°" showValue />
{/* Quick Actions */}

Quick Actions

); }