diff --git a/src/components/ScaleSelector.tsx b/src/components/ScaleSelector.tsx new file mode 100644 index 0000000..758e4a1 --- /dev/null +++ b/src/components/ScaleSelector.tsx @@ -0,0 +1,102 @@ +import { Maximize, Check } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { useModelStore, SCALE_PRESETS, type ScaleRatio } from '@/stores/useModelStore'; +import { toast } from 'sonner'; + +interface ScaleSelectorProps { + /** "compact" = small icon-style for XR HUD, "default" = labeled button for 2D viewer */ + variant?: 'default' | 'compact'; +} + +export function ScaleSelector({ variant = 'default' }: ScaleSelectorProps) { + const { scaleRatio, setScaleRatio, resetFineTuning } = useModelStore(); + + const reductions = SCALE_PRESETS.filter(p => p.factor < 1); + const enlargements = SCALE_PRESETS.filter(p => p.factor > 1); + const oneToOne = SCALE_PRESETS.find(p => p.label === '1:1')!; + + const apply = (r: ScaleRatio) => { + setScaleRatio(r); + // Reset two-hand scale gesture so it doesn't fight the preset. + if (r.label !== '1:1') resetFineTuning(); + toast.success(`Escala ${r.label}`, { + description: 'Medições e ajuste fino mostrados em mm reais.', + }); + }; + + const Trigger = variant === 'compact' ? ( + + + {scaleRatio.label} + + ) : ( + + + Escala {scaleRatio.label} + + ); + + return ( + + {Trigger} + + + + Escala atual + + {scaleRatio.label} + + Medições, ajuste fino e snap são compensados — todos os valores exibidos continuam em mm reais. + + + + + + Real + + + + + + + Reduzir (modelo menor) + + + {reductions.map(p => ( + + ))} + + + + + + Ampliar (modelo maior) + + + {enlargements.map(p => ( + + ))} + + + + + ); +} + +function PresetButton({ + preset, current, onSelect, +}: { preset: ScaleRatio; current: ScaleRatio; onSelect: (r: ScaleRatio) => void }) { + const active = preset.label === current.label; + return ( + onSelect(preset)} + > + {active && } + {preset.label} + + ); +}
+ Escala atual +
{scaleRatio.label}
+ Medições, ajuste fino e snap são compensados — todos os valores exibidos continuam em mm reais. +
+ Real +
+ Reduzir (modelo menor) +
+ Ampliar (modelo maior) +