'use client' import { useScene } from '@pascal-app/core' import { useViewer } from '@pascal-app/viewer' import { AnimatePresence, motion } from 'motion/react' import { useEffect, useMemo } from 'react' import { MaterialPicker } from './../../../components/ui/controls/material-picker' import { TooltipProvider } from './../../../components/ui/primitives/tooltip' import { useIsMobile } from './../../../hooks/use-mobile' import { useReducedMotion } from './../../../hooks/use-reduced-motion' import { resolvePaintTargetFromSelection } from './../../../lib/material-paint' import { cn } from './../../../lib/utils' import useEditor from './../../../store/use-editor' import { CameraActions } from './camera-actions' import { ControlModes } from './control-modes' import { StructureTools } from './structure-tools' import { GridSnapControl, SecondaryToggles } from './view-toggles' // Mobile bottom offset matches the viewer's overlap behind the sheet's // rounded corners (SHEET_OVERLAP_PX in editor-layout-mobile) so the menu sits // just above that strip instead of inside it. const MOBILE_BOTTOM_OFFSET = 24 function PaintMaterialTray() { const activePaintMaterial = useEditor((state) => state.activePaintMaterial) const activePaintTarget = useEditor((state) => state.activePaintTarget) const setActivePaintMaterial = useEditor((state) => state.setActivePaintMaterial) const setActivePaintTarget = useEditor((state) => state.setActivePaintTarget) const selectedIds = useViewer((state) => state.selection.selectedIds) const nodes = useScene((state) => state.nodes) const selectedId = selectedIds.length === 1 ? (selectedIds[0] ?? null) : null useEffect(() => { const selectedPaintTarget = resolvePaintTargetFromSelection({ nodes, selectedId, }) if (selectedPaintTarget) { setActivePaintTarget(selectedPaintTarget) } }, [nodes, selectedId, setActivePaintTarget]) return (