Reset core/viewer/editor/mcp packages and apps/editor from private-editor

Wholesale swap of packages/{core,viewer,editor,mcp} and apps/editor with the
versions from the private editor repo, which is the production source of truth.

Setup changes:
- packages/{core,viewer,editor} versions held at 0.7.0 baseline (matching
  the most recent published release) so a bump=minor publishes 0.8.0
- packages/mcp held at 0.1.1 (never published; first publish will go through
  the new release.yml flow)
- peerDependencies and devDependencies for inter-package @pascal-app/*
  references pinned to ^0.7.0 instead of '*' / 'workspace:*' so they are
  valid for npm consumers
- Root package.json: TypeScript bumped to 6.0.2, added overrides for
  @types/react, @types/react-dom, @types/three to prevent JSX namespace
  fragmentation across the workspace
- release.yml extended to also publish editor and mcp; 'both' option renamed
  to 'all'; added a sync step that updates inter-package peerDeps/devDeps to
  match the new versions on every bump (so viewer/editor/mcp tarballs always
  reference the version of core they were built against)
- Root scripts gained release:editor and release:mcp shortcuts

Verification:
- bun install --frozen-lockfile is consistent
- packages/{core,viewer,mcp} build cleanly, dist/index.d.ts emitted
- packages/editor check-types reports 21 pre-existing errors, identical to
  what private-editor currently reports

Open PRs against editor-v2 will need rebasing/conflict resolution.
This commit is contained in:
Wawa
2026-05-09 20:52:26 +00:00
parent 146f0a846f
commit e618175bba
196 changed files with 5899 additions and 3966 deletions
@@ -834,37 +834,24 @@ function Flutes({
)
}
function DravidianShaftPanels({
node,
shaftY,
shaftHeight,
function DravidianPanelFace({
position,
rotation = 0,
panelHeight,
panelWidth,
rail,
reliefDepth,
panelShape,
}: {
node: ColumnNode
shaftY: number
shaftHeight: number
position: [number, number, number]
rotation?: number
panelHeight: number
panelWidth: number
rail: number
reliefDepth: number
panelShape: NonNullable<ColumnNode['panelShape']>
}) {
const panelCount = Math.max(
node.panelCount ?? 0,
node.style === 'dravidian-carved' || node.shaftDetail === 'panelled' ? 3 : 0,
)
if (panelCount <= 0 || shaftHeight <= 0) return null
const shaftWidth = node.width * 0.72
const shaftDepth = node.depth * 0.72
const panelHeight = Math.min(0.42, shaftHeight / Math.max(4, panelCount + 2))
const panelWidth = node.width * 0.26
const rail = Math.max(0.012, node.width * 0.028)
const reliefDepth = Math.max(0.012, node.panelInsetDepth ?? node.width * 0.025)
const rows = Array.from({ length: panelCount }, (_, index) => (index + 1) / (panelCount + 1))
const panelShape = node.panelShape ?? 'rectangle'
const PanelFace = ({
position,
rotation = 0,
}: {
position: [number, number, number]
rotation?: number
}) => (
return (
<group position={position} rotation={[0, rotation, 0]}>
<MappedBox
depth={reliefDepth}
@@ -917,6 +904,33 @@ function DravidianShaftPanels({
)}
</group>
)
}
function DravidianShaftPanels({
node,
shaftY,
shaftHeight,
}: {
node: ColumnNode
shaftY: number
shaftHeight: number
}) {
const panelCount = Math.max(
node.panelCount ?? 0,
node.style === 'dravidian-carved' || node.shaftDetail === 'panelled' ? 3 : 0,
)
if (panelCount <= 0 || shaftHeight <= 0) return null
const shaftWidth = node.width * 0.72
const shaftDepth = node.depth * 0.72
const panelHeight = Math.min(0.42, shaftHeight / Math.max(4, panelCount + 2))
const panelWidth = node.width * 0.26
const rail = Math.max(0.012, node.width * 0.028)
const reliefDepth = Math.max(0.012, node.panelInsetDepth ?? node.width * 0.025)
const rows = Array.from({ length: panelCount }, (_, index) => (index + 1) / (panelCount + 1))
const panelShape = node.panelShape ?? 'rectangle'
const faceProps = { panelHeight, panelWidth, rail, reliefDepth, panelShape }
return (
<group>
@@ -924,12 +938,23 @@ function DravidianShaftPanels({
const y = shaftY + shaftHeight * t
return (
<group key={rowIndex}>
<PanelFace position={[0, y, shaftDepth / 2 + reliefDepth / 2]} />
<PanelFace position={[0, y, -shaftDepth / 2 - reliefDepth / 2]} />
<PanelFace position={[shaftWidth / 2 + reliefDepth / 2, y, 0]} rotation={Math.PI / 2} />
<PanelFace
<DravidianPanelFace
position={[0, y, shaftDepth / 2 + reliefDepth / 2]}
{...faceProps}
/>
<DravidianPanelFace
position={[0, y, -shaftDepth / 2 - reliefDepth / 2]}
{...faceProps}
/>
<DravidianPanelFace
position={[shaftWidth / 2 + reliefDepth / 2, y, 0]}
rotation={Math.PI / 2}
{...faceProps}
/>
<DravidianPanelFace
position={[-shaftWidth / 2 - reliefDepth / 2, y, 0]}
rotation={Math.PI / 2}
{...faceProps}
/>
</group>
)
@@ -1,6 +1,6 @@
import { type DoorNode, useRegistry, useScene } from '@pascal-app/core'
import { useLayoutEffect, useRef } from 'react'
import { MeshBasicMaterial, type Mesh } from 'three'
import { type Mesh, MeshBasicMaterial } from 'three'
import { useNodeEvents } from '../../../hooks/use-node-events'
const doorHitboxMaterial = new MeshBasicMaterial({ visible: false })
@@ -2,28 +2,12 @@ import { type FenceNode, useRegistry, useScene } from '@pascal-app/core'
import { useLayoutEffect, useMemo, useRef } from 'react'
import type { Mesh } from 'three'
import { useNodeEvents } from '../../../hooks/use-node-events'
import {
createMaterial,
createMaterialFromPresetRef,
DEFAULT_STAIR_MATERIAL,
} from '../../../lib/materials'
import { DEFAULT_STAIR_MATERIAL } from '../../../lib/materials'
export const FenceRenderer = ({ node }: { node: FenceNode }) => {
const ref = useRef<Mesh>(null!)
const handlers = useNodeEvents(node, 'fence')
const material = useMemo(() => {
const presetMaterial = createMaterialFromPresetRef(node.materialPreset)
if (presetMaterial) return presetMaterial
const mat = node.material
if (!mat) return DEFAULT_STAIR_MATERIAL
return createMaterial(mat)
}, [
node.materialPreset,
node.material,
node.material?.preset,
node.material?.properties,
node.material?.texture,
])
const material = useMemo(() => DEFAULT_STAIR_MATERIAL, [])
useRegistry(node.id, 'fence', ref)
useLayoutEffect(() => {
@@ -1,5 +1,5 @@
import { getMaterialPresetByRef, type SlabNode, useRegistry } from '@pascal-app/core'
import { useMemo, useRef } from 'react'
import { useEffect, useMemo, useRef } from 'react'
import type { Mesh } from 'three'
import * as THREE from 'three'
import { useNodeEvents } from '../../../hooks/use-node-events'
@@ -24,10 +24,27 @@ export const StairSegmentRenderer = ({ node }: { node: StairSegmentNode }) => {
const parentNode = node.parentId
? (nodes[node.parentId as AnyNodeId] as StairNode | undefined)
: undefined
const material = useMemo(
() => getStraightStairSegmentBodyMaterials(node, parentNode),
[node, parentNode],
)
const material = useMemo(() => {
return getStraightStairSegmentBodyMaterials(node, parentNode)
}, [
node.materialPreset,
node.material,
node.material?.preset,
node.material?.properties,
node.material?.texture,
parentNode?.materialPreset,
parentNode?.material,
parentNode?.material?.preset,
parentNode?.material?.properties,
parentNode?.material?.texture,
parentNode?.railingMaterialPreset,
parentNode?.railingMaterial,
parentNode?.sideMaterialPreset,
parentNode?.sideMaterial,
parentNode?.treadMaterialPreset,
parentNode?.treadMaterial,
])
const placeholderGeometry = useMemo(() => {
const geometry = new THREE.BufferGeometry()
@@ -112,9 +112,9 @@ export const StairRenderer = ({ node }: { node: StairNode }) => {
receiveShadow
/>
) : null}
{!isSegmentBasedStair ? (
{isSegmentBasedStair ? null : (
<CurvedStairBody bodyMaterials={straightBodyMaterials} stair={node} />
) : null}
)}
<StairRailings material={railingMaterial} stair={node} />
{isSegmentBasedStair ? (
<group name="segments-wrapper" visible={false}>
@@ -292,7 +292,7 @@ function StairRailings({ stair, material }: { stair: StairNode; material: THREE.
))}
{railPaths.slice(1).map((segmentPath, index) => {
const previousPath = railPaths[index]
if (!previousPath || !segmentPath.connectFromPrevious) return null
if (!(previousPath && segmentPath.connectFromPrevious)) return null
if (previousPath.layout.segment.segmentType === 'landing') return null
if (segmentPath.layout.segment.segmentType === 'landing') return null
@@ -451,10 +451,10 @@ function CurvedStairBody({
{isSpiral && (stair.showCenterColumn ?? true) ? (
<mesh
castShadow
receiveShadow
material={sideMaterial}
name="stair-side"
position={[0, spiralColumnHeight / 2, 0]}
receiveShadow
>
<cylinderGeometry
args={[spiralColumnRadius, spiralColumnRadius, spiralColumnHeight, 10]}