Wassim SAMAD e450d8b474
feat(editor): build sidebar + slimmed items panel for standalone editor (#361)
Bring the open-source standalone editor closer to the community editor's
v2 sidebar without pulling in any preset/catalog infrastructure.

- Add a preset-less Build tab (apps/editor) that mirrors the community
  Build sidebar: wall, fence, slab, ceiling, roof, stair, elevator,
  door, window, column, spawn, plus the material-paint panel. Clicking a
  type activates the raw structure tool drawn with the kind's defaults.
- Wire the Build tab into both editor mount points (local + saved scene)
  and give the left rail proper image icons (Scene/Build/Items/Settings)
  instead of letter fallbacks.
- Gate the ItemsPanel Library/Community/Mine source chips and tag filter
  rows behind `showSourceFilter` / `showTagFilters` props (default true,
  so community and external consumers are unchanged). The standalone
  editor passes both off, leaving plain category tabs + full-width search.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 14:51:09 -04:00

118 lines
3.1 KiB
TypeScript

'use client'
import { Editor, ItemsPanel } from '@pascal-app/editor'
import { Hammer, Layers, Package, Settings } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import { BuildTab } from '@/components/build-tab'
import {
CommunityViewerToolbarLeft,
CommunityViewerToolbarRight,
} from '@/components/viewer-toolbar'
// The open-source editor only ships the built-in catalog (no uploaded items),
// so the Library/Community/Mine source chips and tag filters add nothing —
// drop them and keep the panel to plain categories.
function EditorItemsPanel() {
return <ItemsPanel showSourceFilter={false} showTagFilters={false} />
}
const SIDEBAR_TABS = [
{
id: 'site',
label: 'Scene',
component: () => null,
mobileDefaultSnap: 0.5,
mobileIcon: <Layers className="h-5 w-5" />,
icon: (
<Image
alt=""
className="h-8 w-8 object-contain"
height={32}
src="/icons/scene.png"
width={32}
/>
),
},
{
id: 'build',
label: 'Build',
component: BuildTab,
mobileDefaultSnap: 0.5,
mobileIcon: <Hammer className="h-5 w-5" />,
icon: (
<Image
alt=""
className="h-8 w-8 object-contain"
height={32}
src="/icons/build.png"
width={32}
/>
),
},
{
id: 'items',
label: 'Items',
component: EditorItemsPanel,
mobileDefaultSnap: 0.5,
mobileIcon: <Package className="h-5 w-5" />,
icon: (
<Image
alt=""
className="h-8 w-8 object-contain"
height={32}
src="/icons/couch.png"
width={32}
/>
),
},
{
id: 'settings',
label: 'Settings',
component: () => null,
mobileDefaultSnap: 0.5,
mobileIcon: <Settings className="h-5 w-5" />,
icon: (
<Image
alt=""
className="h-8 w-8 object-contain"
height={32}
src="/icons/settings.png"
width={32}
/>
),
},
]
const PROJECT_ID = 'local-editor'
export default function Home() {
return (
<div className="relative h-screen w-screen">
{PROJECT_ID === 'local-editor' && (
<div className="pointer-events-none absolute top-3 left-1/2 z-40 -translate-x-1/2">
<div className="pointer-events-auto flex items-center gap-3 rounded-full border border-border/60 bg-background/90 px-4 py-1.5 text-xs shadow-sm backdrop-blur">
<span className="text-muted-foreground">Local editor — scenes are not saved.</span>
<Link className="font-medium text-foreground hover:underline" href="/scenes">
Open recent scenes
</Link>
<span aria-hidden className="text-muted-foreground">
·
</span>
<Link className="font-medium text-foreground hover:underline" href="/scenes">
Create new
</Link>
</div>
</div>
)}
<Editor
layoutVersion="v2"
projectId={PROJECT_ID}
sidebarTabs={SIDEBAR_TABS}
viewerToolbarLeft={<CommunityViewerToolbarLeft />}
viewerToolbarRight={<CommunityViewerToolbarRight />}
/>
</div>
)
}