Adicionou popover de cores

X-Lovable-Edit-ID: edt-ad717e5e-9246-4f93-b1d9-9c99bc76b631
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-05-15 13:06:59 +00:00
3 changed files with 58 additions and 8 deletions
+49 -4
View File
@@ -1,8 +1,16 @@
import { Eye, EyeOff, Lock, Unlock, Copy, Trash2, Box, Layers } from 'lucide-react';
import { Eye, EyeOff, Lock, Unlock, Copy, Trash2, Box, Layers, Check } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { useModelStore } from '@/stores/useModelStore';
import { toast } from 'sonner';
const COLOR_PALETTE = [
'#ef4444', '#f97316', '#f59e0b', '#eab308', '#84cc16', '#22c55e',
'#10b981', '#14b8a6', '#06b6d4', '#0ea5e9', '#3b82f6', '#6366f1',
'#8b5cf6', '#a855f7', '#d946ef', '#ec4899', '#f43f5e', '#64748b',
'#ffffff', '#1f2937',
];
interface SceneModelListProps {
compact?: boolean;
}
@@ -15,6 +23,7 @@ export function SceneModelList({ compact = false }: SceneModelListProps) {
const toggleVisible = useModelStore((s) => s.toggleModelVisible);
const toggleLocked = useModelStore((s) => s.toggleModelLocked);
const duplicate = useModelStore((s) => s.duplicateModel);
const setModelColor = useModelStore((s) => s.setModelColor);
const max = useModelStore((s) => s.maxModels);
if (models.length === 0) {
@@ -56,11 +65,47 @@ export function SceneModelList({ compact = false }: SceneModelListProps) {
}`}
onClick={() => setActive(m.id)}
>
<div
className="h-2.5 w-2.5 shrink-0 rounded-full ring-1 ring-foreground/20"
<Popover>
<PopoverTrigger asChild>
<button
type="button"
className="h-2.5 w-2.5 shrink-0 rounded-full ring-1 ring-foreground/20 hover:ring-2 hover:ring-primary cursor-pointer"
style={{ backgroundColor: m.color }}
title="Cor da peça"
title="Trocar cor da peça"
onClick={(e) => e.stopPropagation()}
/>
</PopoverTrigger>
<PopoverContent
className="w-auto p-2"
side="right"
align="start"
onClick={(e) => e.stopPropagation()}
>
<p className="font-mono text-[10px] uppercase tracking-widest text-muted-foreground mb-2">
Cor da peça
</p>
<div className="grid grid-cols-5 gap-1.5">
{COLOR_PALETTE.map((c) => {
const selected = c.toLowerCase() === m.color.toLowerCase();
return (
<button
key={c}
type="button"
className="h-6 w-6 rounded-md ring-1 ring-foreground/20 hover:scale-110 transition-transform flex items-center justify-center"
style={{ backgroundColor: c }}
onClick={(e) => {
e.stopPropagation();
setModelColor(m.id, c);
}}
title={c}
>
{selected && <Check className="h-3 w-3" style={{ color: c === '#ffffff' ? '#000' : '#fff' }} />}
</button>
);
})}
</div>
</PopoverContent>
</Popover>
<Box className={`h-3 w-3 shrink-0 ${isActive ? 'text-primary' : 'text-muted-foreground'}`} />
<span className={`flex-1 truncate font-mono ${textSize} ${isActive ? 'text-foreground font-semibold' : 'text-muted-foreground'}`}>
{m.fileName}
+2 -2
View File
@@ -21,7 +21,7 @@ import { convertIFCtoGLB } from "@/lib/convertIFC";
const Viewer = () => {
const navigate = useNavigate();
const { model, xrSupported, addModel, models, maxModels } = useModelStore();
const { model, xrSupported, addModel, models, maxModels, scaleRatio } = useModelStore();
const fileInputRef = useRef<HTMLInputElement>(null);
const [converting, setConverting] = useState(false);
@@ -177,7 +177,7 @@ const Viewer = () => {
<div className="space-y-3">
<InfoItem icon={FileText} label="Arquivo" value={model.fileName} />
<InfoItem icon={Box} label="Tamanho" value={`${(model.fileSize / (1024 * 1024)).toFixed(2)} MB`} />
<InfoItem icon={Ruler} label="Escala" value="1:1 (mm)" />
<InfoItem icon={Ruler} label="Escala" value={`${scaleRatio.label} (mm)`} />
</div>
</div>
+5
View File
@@ -100,6 +100,7 @@ interface ModelStore {
setActiveModel: (id: string | null) => void;
toggleModelVisible: (id: string) => void;
toggleModelLocked: (id: string) => void;
setModelColor: (id: string, color: string) => void;
duplicateModel: (id: string) => void;
clearAllModels: () => void;
maxModels: number;
@@ -243,6 +244,10 @@ export const useModelStore = create<ModelStore>((set, get) => ({
models: state.models.map(m => m.id === id ? { ...m, locked: !m.locked } : m),
})),
setModelColor: (id, color) => set((state) => ({
models: state.models.map(m => m.id === id ? { ...m, color } : m),
})),
duplicateModel: (id) => {
const state = get();
if (state.models.length >= MAX_MODELS) return;