Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
9b89546
国际化1
leapar May 30, 2026
f7359f9
国际化2
leapar May 31, 2026
641bd66
国际化3随浏览器
leapar May 31, 2026
f9570e6
界面UI布局调整
leapar May 31, 2026
251081f
国家化5
leapar May 31, 2026
ca129b5
左侧icon
leapar May 31, 2026
11a3bce
滚动条样式
leapar May 31, 2026
55fc7fd
dialog style
leapar May 31, 2026
3dc0381
settings-panel style
leapar May 31, 2026
e80ed57
Merge branch 'main' of https://github.com/leapar/pascaleditor
leapar Aug 31, 2026
b8c8704
Restore i18n on home page, scene-loader, camera & control actions
leapar Aug 31, 2026
af9d9ea
Restore i18n on action menus, helpers, panel-manager, icon-rail
leapar Aug 31, 2026
d7a991b
Restore i18n on command palette, settings panel, level selector, view…
leapar Aug 31, 2026
51f2a53
Merge remote-tracking branch 'upstream/main' into i18n/restore-lost-t…
leapar Aug 31, 2026
9780af4
fix(i18n): address Bugbot review findings #1, #2, #3, #6
leapar Aug 31, 2026
5edefe0
fix(i18n): address Bugbot review pass 2 — A, B, C
leapar Aug 31, 2026
10f2eed
fix(i18n): add translucent to command palette wall mode (Bugbot D)
leapar Aug 31, 2026
94419f1
fix(i18n): address Bugbot review pass 3 — E, F, G
leapar Aug 31, 2026
7ea5aad
fix(i18n): address Bugbot review pass 4 — H, I, J
leapar Aug 31, 2026
739004a
chore: retrigger Bugbot review
leapar Aug 31, 2026
3fb7c52
fix(i18n): address Bugbot review pass 5 — K, L, M
leapar Aug 31, 2026
96ccaa3
fix(i18n): localize remaining Bugbot findings (N/O/P/Q/R)
leapar Aug 31, 2026
3c27345
chore: retrigger Bugbot review
leapar Aug 31, 2026
0b1dc2b
fix(i18n): address Bugbot review pass 6 — S, T, U
leapar Aug 31, 2026
78bcdb2
fix(i18n): address Bugbot review pass 7 — V
leapar Aug 31, 2026
40ffd9b
fix(i18n): address Bugbot review pass 8 — W, X
leapar Aug 31, 2026
65e737c
fix(i18n): address Bugbot review pass 9 — Y
leapar Aug 31, 2026
6a27f00
fix(i18n): address Bugbot review pass 10 — Z
leapar Aug 31, 2026
4100aa3
fix(editor): resolve pre-existing Bugbot findings #4 and #5
leapar Sep 1, 2026
3e4b021
fix(i18n): localize node-type labels and selection breakdown
leapar Sep 1, 2026
35fc980
chore: retrigger Bugbot review
leapar Sep 1, 2026
d2272e6
fix(i18n): localize site panel, measurement, contextual helper chips
leapar Sep 1, 2026
4204c6f
fix(i18n): localize helper-panel labels, function-tree tips, mouse sh…
leapar Sep 1, 2026
ff0a973
fix(i18n): point wall toolHints at existing nodes.wall.toolHints.* keys
leapar Sep 1, 2026
37d2e50
fix(i18n): localize reshape / sculpt / smart-measurement helper hints
leapar Sep 1, 2026
7b9ce67
fix(i18n): localize persistent-measurement tool hints
leapar Sep 1, 2026
42ee044
fix(i18n): add labelKey to every node toolHint definition
leapar Sep 1, 2026
ce0308c
fix(i18n): localize site panel labels — site/building/structure/furni…
leapar Sep 1, 2026
fbb8aba
fix(i18n): localize delete-confirmation dialog — title, description, …
leapar Sep 1, 2026
21d2b55
fix(i18n): localize multi-selection summary panel — buttons, header, …
leapar Sep 1, 2026
33111b1
fix(i18n): localize Build tab tile labels, MEP sub-grid, roof-type an…
leapar Sep 1, 2026
1ee5d72
fix(i18n): localize paint/sculpt/material controls — material picker,…
leapar Sep 1, 2026
d0de091
fix(i18n): localize material catalog labels + Site header
leapar Sep 1, 2026
7ec07b7
fix(i18n): add 7 missing keys — common.directions.{left,right}, nodes…
leapar Sep 1, 2026
9f30efd
chore(i18n): delete 23 orphan keys — panel.nodeType.streetscape:* + 9…
leapar Sep 1, 2026
0df5001
fix(i18n): wire chimney panel labels to nodes.chimney.* keys
leapar Sep 1, 2026
2d89e88
fix(i18n): wire box-vent panel labels to nodes.boxVent.* + common.* keys
leapar Sep 1, 2026
b62cd02
fix(i18n): wire door panel labels to nodes.door.* + common.* keys
leapar Sep 1, 2026
ba1f415
fix(i18n): wire dormer panel labels to nodes.dormer.* + common.* keys
leapar Sep 1, 2026
49d5a57
fix(i18n): wire ceiling panel labels to nodes.ceiling.* + common.* keys
leapar Sep 1, 2026
ee060ae
fix(i18n): wire skylight panel labels to nodes.skylight.* + common.* …
leapar Sep 1, 2026
328c582
fix(i18n): wire wall panel labels to nodes.wall.* + common.* keys
leapar Sep 1, 2026
7a23764
fix(i18n): wire stair panel labels to nodes.stair.* + common.* keys
leapar Sep 1, 2026
1bc8709
fix(i18n): wire roof panel labels to nodes.roof.* + common.* keys
leapar Sep 1, 2026
3f8cd96
fix(block): pass translator to materialRefLabel for catalog labelKey …
leapar Sep 1, 2026
727eaa2
fix(definition): unbreak presentation.label by using literal English
Sep 1, 2026
8ee210b
fix(i18n): normalize site panel title + 6 tool-hint entries
Sep 1, 2026
1e38424
fix(i18n): wire cupola tool hints to nodes.cupola.toolHints.place
Sep 1, 2026
c2f519e
fix(i18n): wire elevator panel labels to nodes.elevator.* + common.* …
Sep 1, 2026
721ddbe
fix(i18n): wire ceiling panel height presets + mode + info section
Sep 1, 2026
323e1a3
fix(i18n): wire roof-segment panel labels to nodes.roofSegment.* + co…
leapar Sep 1, 2026
969d279
fix(i18n): wire column panel labels to nodes.column.* + common.* keys
leapar Sep 1, 2026
79f3c6d
fix(i18n): wire stair + stair-segment panels to nodes.stair(*) keys
leapar Sep 1, 2026
d39efd6
fix(i18n): wire ridge-vent panel labels to nodes.ridgeVent.* keys
leapar Sep 1, 2026
aa1e038
fix(i18n): add 8 nodes.eyebrowVent.* + 11 nodes.turbineVent.* keys
leapar Sep 1, 2026
3ba9d6a
fix(i18n): wire eyebrow-vent panel labels to nodes.eyebrowVent.* keys
leapar Sep 1, 2026
e25119f
fix(i18n): wire turbine-vent panel labels to nodes.turbineVent.* keys
leapar Sep 1, 2026
4ca42e0
fix(i18n): add 9 solar-panel keys (presets, fallback title, notices)
leapar Sep 1, 2026
1cf3c9b
fix(i18n): wire solar-panel panel labels to nodes.solarPanel.* keys
leapar Sep 1, 2026
49d8817
fix(i18n): add 13 slab keys (floor/surface/rim/base, foundation, terr…
leapar Sep 1, 2026
692a181
fix(i18n): wire slab panel labels to nodes.slab.* + common.* keys
leapar Sep 1, 2026
ee39ce8
fix(i18n): add 21 roof keys (defaultName.*, kindLabel.*, addCupola, a…
leapar Sep 1, 2026
556d404
fix(i18n): wire roof panel labels to nodes.roof.* + common.* keys
leapar Sep 1, 2026
1a9b571
fix(i18n): add 36 wall keys (top/bottom, followsLevel/customHeight, f…
leapar Sep 1, 2026
ef1fddf
fix(i18n): wire wall panel labels to nodes.wall.* + common.* keys
leapar Sep 1, 2026
c11a14f
fix(i18n): add 47 cabinet keys (handles, fronts, tiers, animation, pl…
leapar Sep 1, 2026
be8df63
fix(i18n): wire cabinet panel labels to nodes.cabinet.* + common.* keys
leapar Sep 1, 2026
97b1260
fix(i18n): add 53 constructionDimension keys (mode/datum/terminator/p…
leapar Sep 1, 2026
c94b217
fix(i18n): wire construction-dimension panel labels to nodes.construc…
leapar Sep 1, 2026
410c34b
fix(i18n): add 23 block keys (panel/slot notice/face labels/actions)
leapar Sep 1, 2026
da95325
fix(i18n): wire block panel labels to nodes.block.* keys
leapar Sep 1, 2026
b6a4fad
fix(i18n): add 6 dormer keys (roofType/pitchDirection/pitchRise/riseB…
leapar Sep 1, 2026
8612b09
fix(i18n): wire dormer panel labels to nodes.dormer.* keys
leapar Sep 1, 2026
744c22a
fix(i18n): add 6 cupola keys + common.style (cupola/dome/pyramid/fini…
leapar Sep 1, 2026
531ea5c
fix(i18n): wire cupola panel labels to nodes.cupola.* and common.* keys
leapar Sep 1, 2026
20f8f40
fix(i18n): add 1 ceiling key (currently {value})
leapar Sep 1, 2026
a2a135a
fix(i18n): wire ceiling panel 'currently' label to nodes.ceiling.curr…
leapar Sep 1, 2026
bce7686
fix(i18n): add 5 keys - chimney/skylight/boxVent/elevator fallback + …
leapar Sep 1, 2026
847c9c1
fix(i18n): wire chimney/box-vent/skylight/elevator fallback titles + …
leapar Sep 1, 2026
5a84d53
fix(i18n): add 58 panel.nodeType.* keys (block, box-vent, building, c…
leapar Sep 1, 2026
2101820
fix(i18n): wire presentation.label to panel.nodeType.* catalog in 3 c…
leapar Sep 1, 2026
ebf1ee3
feat(core): add labelKey/descriptionKey to Presentation type
leapar Sep 1, 2026
1068ae2
feat(editor): build tab reads presentation.labelKey
leapar Sep 1, 2026
67ffaea
feat(nodes): add presentation.labelKey to all 47 node definitions
leapar Sep 1, 2026
d8a8762
feat(core): add labelKey/optionLabelKeys to ParamGroup/ParamField
leapar Sep 1, 2026
e21e77a
feat(editor): inspector + field-control resolve labelKey / optionLabe…
leapar Sep 1, 2026
07d5973
feat(nodes): wire labelKey + optionLabelKeys on auto-derived descriptors
leapar Sep 1, 2026
2289305
feat(ifc-converter): self-contained i18n module
leapar Sep 1, 2026
3ddffab
feat(ifc-converter): add ifcConverter.* dictionary keys (104)
leapar Sep 1, 2026
e0242bd
feat(ifc-converter): wire all UI surfaces to ifcConverter.* keys
leapar Sep 1, 2026
4801969
feat(nodes): wire missing labelKey on 55 parametric groups
leapar Sep 1, 2026
7a87109
feat(i18n): add keys for title/label/aria-label audit
leapar Sep 1, 2026
4c0c302
fix(i18n): wire title/label/aria-label JSX attributes to translations
leapar Sep 1, 2026
34c6b5c
fix(i18n): address Bugbot High/Medium findings from PR #740 review
leapar Sep 1, 2026
9b119f6
Merge upstream/main: resolve snapshot-capture-overlay conflict
leapar Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
19 changes: 19 additions & 0 deletions apps/editor/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@
scrollbar-width: none; /* Firefox */
}

/* Custom scrollbar — thin, dark-themed */
::-webkit-scrollbar {
width: 5px;
height: 5px;
}

::-webkit-scrollbar-track {
background: #2c2c2e;
}

::-webkit-scrollbar-thumb {
background: oklch(1 0 0 / 30%);
border-radius: 9999px;
}

::-webkit-scrollbar-thumb:hover {
background: oklch(1 0 0 / 50%);
}

@media (prefers-reduced-motion: reduce) {
*,
*::before,
Expand Down
147 changes: 75 additions & 72 deletions apps/editor/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use client'

import { Editor, ItemsPanel } from '@pascal-app/editor'
import { Editor, ItemsPanel, useTranslations } from '@pascal-app/editor'
import { Hammer, Layers, Package, Settings } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import { useMemo } from 'react'
import { BuildTab } from '@/components/build-tab'
import {
CommunityViewerToolbarLeft,
Expand All @@ -17,89 +18,91 @@ 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.webp"
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.webp"
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.webp"
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.webp"
width={32}
/>
),
},
]

const PROJECT_ID = 'local-editor'

export default function Home() {
const t = useTranslations()
const SIDEBAR_TABS = useMemo(
() => [
{
id: 'site',
label: t('sidebar.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.webp"
width={32}
/>
),
},
{
id: 'build',
label: t('sidebar.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.webp"
width={32}
/>
),
},
{
id: 'items',
label: t('sidebar.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.webp"
width={32}
/>
),
},
{
id: 'settings',
label: t('sidebar.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.webp"
width={32}
/>
),
},
],
[t],
)

return (
<div className="relative h-screen w-screen">
{PROJECT_ID === 'local-editor' && (
<div className="pointer-events-none absolute top-14 left-1/2 z-40 -translate-x-1/2">
<div className="pointer-events-none flex max-w-[min(92vw,42rem)] flex-wrap items-center justify-center gap-x-3 gap-y-1 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">
Blank canvas — saved scenes are under Scenes (not this page).
</span>
<span className="text-muted-foreground">{t('editor.localWarning')}</span>
Comment thread
cursor[bot] marked this conversation as resolved.
<Link
className="pointer-events-auto font-medium text-foreground hover:underline"
href="/scenes"
>
Open saved scenes
{t('editor.openSavedScenes')}
Comment thread
cursor[bot] marked this conversation as resolved.
Comment thread
cursor[bot] marked this conversation as resolved.
</Link>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions apps/editor/app/scenes/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function ScenesLayout({
children,
}: {
children: React.ReactNode
}) {
return <div className="dark min-h-screen bg-background">{children}</div>
}
100 changes: 14 additions & 86 deletions apps/editor/app/scenes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { headers } from 'next/headers'
import Link from 'next/link'
import { CreateSceneButton } from '@/components/save-button'
import type { SceneMeta } from '@/components/scene-loader'
import { ScenesList } from './scenes-list'

export const dynamic = 'force-dynamic'

Expand All @@ -20,98 +21,25 @@ async function resolveBaseUrl(): Promise<string> {

async function fetchScenes(): Promise<SceneMeta[]> {
const base = await resolveBaseUrl()
const response = await fetch(`${base}/api/scenes?limit=50`, {
cache: 'no-store',
})
if (!response.ok) {
return []
}
const payload = (await response.json()) as { scenes?: SceneMeta[] } | SceneMeta[]
if (Array.isArray(payload)) {
return payload
}
return payload.scenes ?? []
}

function formatDate(iso: string): string {
try {
return new Date(iso).toLocaleString()
const response = await fetch(`${base}/api/scenes?limit=50`, {
cache: 'no-store',
})
if (!response.ok) {
return []
}
const payload = (await response.json()) as { scenes?: SceneMeta[] } | SceneMeta[]
if (Array.isArray(payload)) {
return payload
}
return payload.scenes ?? []
} catch {
return iso
return []
}
}

export default async function ScenesPage() {
const scenes = await fetchScenes()

return (
<div className="min-h-screen bg-background">
<header className="sticky top-0 z-10 border-border border-b bg-background/95 backdrop-blur">
<div className="container mx-auto flex items-center justify-between gap-4 px-6 py-4">
<nav className="flex items-center gap-4 text-sm">
<Link
className="text-muted-foreground transition-colors hover:text-foreground"
href="/"
>
Home
</Link>
<span className="text-muted-foreground">/</span>
<span className="font-medium text-foreground">Scenes</span>
</nav>
<CreateSceneButton />
</div>
</header>

<main className="container mx-auto max-w-5xl px-6 py-12">
<h1 className="mb-2 font-bold text-3xl">Your scenes</h1>
<p className="mb-8 text-muted-foreground text-sm">
{scenes.length === 0
? 'No scenes yet. Create one to get started.'
: `${scenes.length} scene${scenes.length === 1 ? '' : 's'}.`}
</p>

{scenes.length === 0 ? (
<div className="rounded-xl border border-border/60 border-dashed bg-background p-12 text-center">
<p className="text-muted-foreground text-sm">You haven&apos;t saved any scenes yet.</p>
<div className="mt-4 flex justify-center">
<CreateSceneButton />
</div>
</div>
) : (
<ul className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{scenes.map((scene) => (
<li key={scene.id}>
<Link
className="group block rounded-xl border border-border/60 bg-background p-4 transition-colors hover:border-border hover:bg-accent/30"
href={`/scene/${scene.id}`}
>
<div className="flex aspect-video items-center justify-center overflow-hidden rounded-lg bg-accent/30">
{scene.thumbnailUrl ? (
// eslint-disable-next-line @next/next/no-img-element
<img
alt={scene.name}
className="h-full w-full object-cover"
src={scene.thumbnailUrl}
/>
) : (
<span className="text-muted-foreground text-xs">No thumbnail</span>
)}
</div>
<div className="mt-3">
<h2 className="truncate font-semibold text-sm group-hover:text-foreground">
{scene.name}
</h2>
<div className="mt-1 flex items-center justify-between text-muted-foreground text-xs">
<span>{scene.nodeCount} nodes</span>
<time dateTime={scene.updatedAt}>{formatDate(scene.updatedAt)}</time>
</div>
</div>
</Link>
</li>
))}
</ul>
)}
</main>
</div>
)
return <ScenesList scenes={scenes} />
}
Loading