'use client' import { Icon as IconifyIcon } from '@iconify/react' import { useViewer } from '@pascal-app/viewer' import { Check, ChevronsLeft, ChevronsRight, Columns2, Eye, Footprints, Moon, Sun } from 'lucide-react' import { useCallback } from 'react' import { cn } from '../../lib/utils' import useEditor from '../../store/use-editor' import type { GridSnapStep, ViewMode } from '../../store/use-editor' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from './primitives/dropdown-menu' import { useSidebarStore } from './primitives/sidebar' import { Tooltip, TooltipContent, TooltipTrigger } from './primitives/tooltip' // ── Shared styles ─────────────────────────────────────────────────────────── /** Container for a group of buttons — no padding, overflow-hidden clips children flush. */ const TOOLBAR_CONTAINER = 'inline-flex h-8 items-stretch overflow-hidden rounded-xl border border-border bg-background/90 shadow-2xl backdrop-blur-md' /** Ghost button inside a container — flush edges, no individual border/radius. */ const TOOLBAR_BTN = 'flex items-center justify-center w-8 text-muted-foreground/80 transition-colors hover:bg-white/8 hover:text-foreground/90' // ── View mode segmented control ───────────────────────────────────────────── const VIEW_MODES: { id: ViewMode; label: string; icon: React.ReactNode }[] = [ { id: '3d', label: '3D', icon: , }, { id: '2d', label: '2D', icon: , }, { id: 'split', label: 'Split', icon: , }, ] function ViewModeControl() { const viewMode = useEditor((s) => s.viewMode) const setViewMode = useEditor((s) => s.setViewMode) return (
{VIEW_MODES.map((mode) => { const isActive = viewMode === mode.id return ( ) })}
) } // ── Collapse sidebar button ───────────────────────────────────────────────── function CollapseSidebarButton() { const isCollapsed = useSidebarStore((s) => s.isCollapsed) const setIsCollapsed = useSidebarStore((s) => s.setIsCollapsed) const toggle = useCallback(() => { setIsCollapsed(!isCollapsed) }, [isCollapsed, setIsCollapsed]) return (
) } // ── Right toolbar buttons ─────────────────────────────────────────────────── function WalkthroughButton() { const isFirstPersonMode = useEditor((s) => s.isFirstPersonMode) const setFirstPersonMode = useEditor((s) => s.setFirstPersonMode) const toggle = () => { setFirstPersonMode(!isFirstPersonMode) } return ( Walkthrough ) } function UnitToggle() { const unit = useViewer((s) => s.unit) const setUnit = useViewer((s) => s.setUnit) return ( {unit === 'metric' ? 'Metric (m)' : 'Imperial (ft)'} ) } function ThemeToggle() { const theme = useViewer((s) => s.theme) const setTheme = useViewer((s) => s.setTheme) return ( {theme === 'dark' ? 'Dark' : 'Light'} ) } // ── Level mode toggle ─────────────────────────────────────────────────────── const levelModeOrder = ['stacked', 'exploded', 'solo'] as const const levelModeLabels: Record = { manual: 'Stack', stacked: 'Stack', exploded: 'Exploded', solo: 'Solo', } const gridSnapOrder: GridSnapStep[] = [0.5, 0.25, 0.1, 0.05] const gridSnapLabels: Record = { 0.5: '0.50', 0.25: '0.25', 0.1: '0.10', 0.05: '0.05', } function formatGridSnapStep(step: GridSnapStep): string { return gridSnapLabels[step] } function LevelModeToggle() { const levelMode = useViewer((s) => s.levelMode) const setLevelMode = useViewer((s) => s.setLevelMode) const cycle = () => { if (levelMode === 'manual') { setLevelMode('stacked') return } const idx = levelModeOrder.indexOf(levelMode as (typeof levelModeOrder)[number]) const next = levelModeOrder[(idx + 1) % levelModeOrder.length] if (next) setLevelMode(next) } const isDefault = levelMode === 'stacked' || levelMode === 'manual' return ( Levels: {levelMode === 'manual' ? 'Manual' : levelModeLabels[levelMode]} ) } function GridSnapToggle() { const gridSnapStep = useEditor((s) => s.gridSnapStep) const setGridSnapStep = useEditor((s) => s.setGridSnapStep) return ( Grid snap: {formatGridSnapStep(gridSnapStep)} {gridSnapOrder.map((step) => { const isActive = step === gridSnapStep return ( setGridSnapStep(step)}> {formatGridSnapStep(step)} {isActive ? : } ) })} ) } // ── Wall mode toggle ──────────────────────────────────────────────────────── const wallModeOrder = ['cutaway', 'up', 'down'] as const const wallModeConfig: Record = { up: { icon: '/icons/room.png', label: 'Full height' }, cutaway: { icon: '/icons/wallcut.png', label: 'Cutaway' }, down: { icon: '/icons/walllow.png', label: 'Low' }, } function WallModeToggle() { const wallMode = useViewer((s) => s.wallMode) const setWallMode = useViewer((s) => s.setWallMode) const cycle = () => { const idx = wallModeOrder.indexOf(wallMode as (typeof wallModeOrder)[number]) const next = wallModeOrder[(idx + 1) % wallModeOrder.length] if (next) setWallMode(next) } const config = wallModeConfig[wallMode] ?? wallModeConfig.cutaway! return ( Walls: {config.label} ) } // ── Camera mode toggle ────────────────────────────────────────────────────── function CameraModeToggle() { const cameraMode = useViewer((s) => s.cameraMode) const setCameraMode = useViewer((s) => s.setCameraMode) return ( {cameraMode === 'perspective' ? 'Perspective' : 'Orthographic'} ) } function PreviewButton() { return ( Preview mode ) } // ── Composed toolbar sections ─────────────────────────────────────────────── export function ViewerToolbarLeft() { return ( <> ) } export function ViewerToolbarRight() { return (
) }