fix z-index viewer
This commit is contained in:
@@ -1,9 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import { type AnyNode, type AnyNodeId, type BuildingNode, type LevelNode, type ZoneNode, useScene } from '@pascal-app/core'
|
||||
import {
|
||||
type AnyNode,
|
||||
type AnyNodeId,
|
||||
type BuildingNode,
|
||||
type LevelNode,
|
||||
useScene,
|
||||
type ZoneNode,
|
||||
} from '@pascal-app/core'
|
||||
import { useViewer } from '@pascal-app/viewer'
|
||||
import {
|
||||
ArrowLeft,
|
||||
Box,
|
||||
ChevronRight,
|
||||
Diamond,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Image,
|
||||
Layers,
|
||||
Layers2,
|
||||
} from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { ArrowLeft, Box, ChevronRight, Diamond, Eye, EyeOff, Image, Layers, Layers2 } from 'lucide-react'
|
||||
import type { ProjectOwner } from '@/features/community/lib/projects/types'
|
||||
|
||||
const getNodeName = (node: AnyNode): string => {
|
||||
@@ -23,7 +40,12 @@ interface ViewerOverlayProps {
|
||||
canShowGuides?: boolean
|
||||
}
|
||||
|
||||
export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShowGuides = true }: ViewerOverlayProps) => {
|
||||
export const ViewerOverlay = ({
|
||||
projectName,
|
||||
owner,
|
||||
canShowScans = true,
|
||||
canShowGuides = true,
|
||||
}: ViewerOverlayProps) => {
|
||||
const selection = useViewer((s) => s.selection)
|
||||
const nodes = useScene((s) => s.nodes)
|
||||
const showScans = useViewer((s) => s.showScans)
|
||||
@@ -32,17 +54,21 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
const levelMode = useViewer((s) => s.levelMode)
|
||||
const wallMode = useViewer((s) => s.wallMode)
|
||||
|
||||
const building = selection.buildingId ? (nodes[selection.buildingId] as BuildingNode | undefined) : null
|
||||
const building = selection.buildingId
|
||||
? (nodes[selection.buildingId] as BuildingNode | undefined)
|
||||
: null
|
||||
const level = selection.levelId ? (nodes[selection.levelId] as LevelNode | undefined) : null
|
||||
const zone = selection.zoneId ? (nodes[selection.zoneId] as ZoneNode | undefined) : null
|
||||
|
||||
// Get the first selected item (if any)
|
||||
const selectedNode = selection.selectedIds.length > 0
|
||||
const selectedNode =
|
||||
selection.selectedIds.length > 0
|
||||
? (nodes[selection.selectedIds[0] as AnyNodeId] as AnyNode | undefined)
|
||||
: null
|
||||
|
||||
// Get all levels for the selected building
|
||||
const levels = building?.children
|
||||
const levels =
|
||||
building?.children
|
||||
.map((id) => nodes[id as AnyNodeId] as LevelNode | undefined)
|
||||
.filter((n): n is LevelNode => n?.type === 'level')
|
||||
.sort((a, b) => a.level - b.level) ?? []
|
||||
@@ -69,7 +95,7 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
return (
|
||||
<>
|
||||
{/* Unified top-left card */}
|
||||
<div className="absolute top-4 left-4 z-10 flex flex-col gap-3">
|
||||
<div className="absolute top-4 left-4 z-20 flex flex-col gap-3">
|
||||
<div className="bg-white/80 backdrop-blur-sm rounded-lg rounded-smooth shadow-[0_1px_4px_rgba(0,0,0,0.06),0_0_0_1px_rgba(0,0,0,0.03)] overflow-hidden">
|
||||
{/* Project info + back */}
|
||||
<div className="flex items-center gap-3 px-3 py-2">
|
||||
@@ -132,7 +158,9 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
{zone && (
|
||||
<>
|
||||
<ChevronRight className="w-3 h-3 text-neutral-400" />
|
||||
<span className={`transition-colors truncate ${selectedNode ? 'text-neutral-500' : 'text-neutral-800 font-medium'}`}>
|
||||
<span
|
||||
className={`transition-colors truncate ${selectedNode ? 'text-neutral-500' : 'text-neutral-800 font-medium'}`}
|
||||
>
|
||||
{zone.name}
|
||||
</span>
|
||||
</>
|
||||
@@ -141,7 +169,9 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
{selectedNode && zone && (
|
||||
<>
|
||||
<ChevronRight className="w-3 h-3 text-neutral-400" />
|
||||
<span className="text-neutral-800 font-medium truncate">{getNodeName(selectedNode)}</span>
|
||||
<span className="text-neutral-800 font-medium truncate">
|
||||
{getNodeName(selectedNode)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -171,7 +201,7 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
</div>
|
||||
|
||||
{/* Controls Panel - Top Right */}
|
||||
<div className="absolute top-4 right-4 z-10 flex flex-col gap-2">
|
||||
<div className="absolute top-4 right-4 z-20 flex flex-col gap-2">
|
||||
{/* Visibility Controls */}
|
||||
{(canShowScans || canShowGuides) && (
|
||||
<div className="flex flex-col gap-1 bg-white/80 backdrop-blur-sm rounded-lg p-2 shadow-[0_1px_4px_rgba(0,0,0,0.06),0_0_0_1px_rgba(0,0,0,0.03)]">
|
||||
@@ -205,7 +235,11 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
<div className="flex flex-col gap-1 bg-white/80 backdrop-blur-sm rounded-lg p-2 shadow-[0_1px_4px_rgba(0,0,0,0.06),0_0_0_1px_rgba(0,0,0,0.03)]">
|
||||
<span className="text-xs text-neutral-500 px-2 pb-1">Camera</span>
|
||||
<button
|
||||
onClick={() => useViewer.getState().setCameraMode(cameraMode === 'perspective' ? 'orthographic' : 'perspective')}
|
||||
onClick={() =>
|
||||
useViewer
|
||||
.getState()
|
||||
.setCameraMode(cameraMode === 'perspective' ? 'orthographic' : 'perspective')
|
||||
}
|
||||
className="flex items-center gap-2 px-2 py-1 rounded text-sm text-neutral-700 hover:bg-neutral-100 transition-colors"
|
||||
>
|
||||
{cameraMode === 'perspective' ? (
|
||||
@@ -223,7 +257,9 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
<button
|
||||
onClick={() => useViewer.getState().setLevelMode('stacked')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
levelMode === 'stacked' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
levelMode === 'stacked'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<Layers className="w-4 h-4" />
|
||||
@@ -232,7 +268,9 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
<button
|
||||
onClick={() => useViewer.getState().setLevelMode('exploded')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
levelMode === 'exploded' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
levelMode === 'exploded'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<Layers2 className="w-4 h-4" />
|
||||
@@ -241,7 +279,9 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
<button
|
||||
onClick={() => useViewer.getState().setLevelMode('solo')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
levelMode === 'solo' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
levelMode === 'solo'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<Diamond className="w-4 h-4" />
|
||||
@@ -255,10 +295,18 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
<button
|
||||
onClick={() => useViewer.getState().setWallMode('cutaway')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
wallMode === 'cutaway' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
wallMode === 'cutaway'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Cutaway" height={16} src="/icons/wallcut.png" width={16} className="w-4 h-4" />
|
||||
<img
|
||||
alt="Cutaway"
|
||||
height={16}
|
||||
src="/icons/wallcut.png"
|
||||
width={16}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
Cutaway
|
||||
</button>
|
||||
<button
|
||||
@@ -267,13 +315,21 @@ export const ViewerOverlay = ({ projectName, owner, canShowScans = true, canShow
|
||||
wallMode === 'up' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Full Height" height={16} src="/icons/room.png" width={16} className="w-4 h-4" />
|
||||
<img
|
||||
alt="Full Height"
|
||||
height={16}
|
||||
src="/icons/room.png"
|
||||
width={16}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
Full Height
|
||||
</button>
|
||||
<button
|
||||
onClick={() => useViewer.getState().setWallMode('down')}
|
||||
className={`flex items-center gap-2 px-2 py-1 rounded text-sm transition-colors ${
|
||||
wallMode === 'down' ? 'bg-blue-500 text-white' : 'text-neutral-700 hover:bg-neutral-100'
|
||||
wallMode === 'down'
|
||||
? 'bg-blue-500 text-white'
|
||||
: 'text-neutral-700 hover:bg-neutral-100'
|
||||
}`}
|
||||
>
|
||||
<img alt="Low" height={16} src="/icons/walllow.png" width={16} className="w-4 h-4" />
|
||||
|
||||
Reference in New Issue
Block a user