chore(editor): delete legacy door/window presets UI (#339) (#343)

Retires the door/window-only `PresetsPopover`, its `presets-context`
adapter, and the `PresetThumbnailGenerator` ahead of the unified preset
system landing via the items catalog. Drops the public exports
(`PresetsPopover`, `PresetsAdapter`, `PresetsTab`, `PresetsProvider`,
`usePresetsAdapter`) and the matching `presetsAdapter` prop / provider
wrappers on `<Editor>`, plus the `preset:generate-thumbnail` /
`preset:thumbnail-updated` event types in core. Door and window panels
now render the regular parametric inspector with no popover trigger;
`materialPreset` stays untouched.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-05-28 10:08:41 -04:00
committed by GitHub
co-authored by Claude Opus 4.7
parent 1fd59dd9cd
commit 0ad0ac1591
8 changed files with 50 additions and 1007 deletions
+2 -97
View File
@@ -1,29 +1,20 @@
'use client'
import {
type AnyNode,
type AnyNodeId,
DoorNode,
emitter,
useInteractive,
useScene,
} from '@pascal-app/core'
import { type AnyNode, type AnyNodeId, DoorNode, useInteractive, useScene } from '@pascal-app/core'
import {
ActionButton,
ActionGroup,
cn,
PanelSection,
PanelWrapper,
PresetsPopover,
SegmentedControl,
SliderControl,
ToggleControl,
triggerSFX,
useEditor,
usePresetsAdapter,
} from '@pascal-app/editor'
import { useViewer } from '@pascal-app/viewer'
import { BookMarked, Copy, DoorOpen, FlipHorizontal2, Move, Trash2 } from 'lucide-react'
import { Copy, DoorOpen, FlipHorizontal2, Move, Trash2 } from 'lucide-react'
import { useCallback, useRef } from 'react'
const doorTypeOptions = [
@@ -151,8 +142,6 @@ export default function DoorPanel() {
value: unknown
} | null>(null)
const adapter = usePresetsAdapter()
const node = useScene((s) =>
selectedId ? (s.nodes[selectedId as AnyNode['id']] as DoorNode | undefined) : undefined,
)
@@ -312,69 +301,6 @@ export default function DoorPanel() {
handleUpdate({ segments: updated })
}
const getDoorPresetData = useCallback(() => {
if (!node) return null
return {
doorCategory: node.doorCategory,
doorType: node.doorType,
leafCount: node.leafCount,
operationState: node.operationState,
slideDirection: node.slideDirection,
trackStyle: node.trackStyle,
garagePanelCount: node.garagePanelCount,
width: node.width,
height: node.height,
frameThickness: node.frameThickness,
frameDepth: node.frameDepth,
openingKind: node.openingKind,
openingShape: node.openingShape,
openingRadiusMode: node.openingRadiusMode ?? 'all',
openingTopRadii: node.openingTopRadii ?? [0.15, 0.15],
cornerRadius: node.cornerRadius,
archHeight: node.archHeight,
openingRevealRadius: node.openingRevealRadius,
contentPadding: node.contentPadding,
hingesSide: node.hingesSide,
swingDirection: node.swingDirection,
threshold: node.threshold,
thresholdHeight: node.thresholdHeight,
handle: node.handle,
handleHeight: node.handleHeight,
handleSide: node.handleSide,
doorCloser: node.doorCloser,
panicBar: node.panicBar,
panicBarHeight: node.panicBarHeight,
segments: node.segments,
}
}, [node])
const handleSavePreset = useCallback(
async (name: string) => {
const data = getDoorPresetData()
if (!(data && selectedId)) return
const presetId = await adapter.savePreset('door', name, data)
if (presetId) emitter.emit('preset:generate-thumbnail', { presetId, nodeId: selectedId })
},
[getDoorPresetData, selectedId, adapter],
)
const handleOverwritePreset = useCallback(
async (id: string) => {
const data = getDoorPresetData()
if (!(data && selectedId)) return
await adapter.overwritePreset('door', id, data)
emitter.emit('preset:generate-thumbnail', { presetId: id, nodeId: selectedId })
},
[getDoorPresetData, selectedId, adapter],
)
const handleApplyPreset = useCallback(
(data: Record<string, unknown>) => {
handleUpdate(data as Partial<DoorNode>)
},
[handleUpdate],
)
if (!(node && node.type === 'door' && selectedId)) return null
const hSum = node.segments.reduce((s, seg) => s + seg.heightRatio, 0)
@@ -594,27 +520,6 @@ export default function DoorPanel() {
title={node.name || 'Door'}
width={320}
>
{/* Presets strip */}
<div className="border-border/30 border-b px-3 pt-2.5 pb-1.5">
<PresetsPopover
isAuthenticated={adapter.isAuthenticated}
onApply={handleApplyPreset}
onDelete={(id) => adapter.deletePreset(id)}
onFetchPresets={(tab) => adapter.fetchPresets('door', tab)}
onOverwrite={handleOverwritePreset}
onRename={(id, name) => adapter.renamePreset(id, name)}
onSave={handleSavePreset}
onToggleCommunity={adapter.togglePresetCommunity}
tabs={adapter.tabs}
type="door"
>
<button className="flex w-full items-center gap-2 rounded-lg border border-border/50 bg-[#2C2C2E] px-3 py-2 font-medium text-muted-foreground text-xs transition-colors hover:bg-[#3e3e3e] hover:text-foreground">
<BookMarked className="h-3.5 w-3.5 shrink-0" />
<span>Presets</span>
</button>
</PresetsPopover>
</div>
<PanelSection title="Type">
<div className="flex flex-col gap-2 px-1 pb-1">
<SegmentedControl
+1 -83
View File
@@ -3,7 +3,6 @@
import {
type AnyNode,
type AnyNodeId,
emitter,
useInteractive,
useScene,
WindowNode,
@@ -14,16 +13,14 @@ import {
cn,
PanelSection,
PanelWrapper,
PresetsPopover,
SegmentedControl,
SliderControl,
ToggleControl,
triggerSFX,
useEditor,
usePresetsAdapter,
} from '@pascal-app/editor'
import { useViewer } from '@pascal-app/viewer'
import { BookMarked, Copy, FlipHorizontal2, Move, Trash2 } from 'lucide-react'
import { Copy, FlipHorizontal2, Move, Trash2 } from 'lucide-react'
import { useCallback, useRef } from 'react'
function isSameWindowValue(current: unknown, next: unknown): boolean {
@@ -104,8 +101,6 @@ export default function WindowPanel() {
value: unknown
} | null>(null)
const adapter = usePresetsAdapter()
const node = useScene((s) =>
selectedId ? (s.nodes[selectedId as AnyNode['id']] as WindowNode | undefined) : undefined,
)
@@ -251,62 +246,6 @@ export default function WindowPanel() {
setSelection({ selectedIds: [] })
}, [node, setMovingNode, setSelection])
const getWindowPresetData = useCallback(() => {
if (!node) return null
return {
width: node.width,
height: node.height,
windowType: node.windowType,
operationState: node.operationState,
awningDirection: node.awningDirection,
casementStyle: node.casementStyle,
hingesSide: node.hingesSide,
frameThickness: node.frameThickness,
frameDepth: node.frameDepth,
openingKind: node.openingKind,
openingShape: node.openingShape,
openingRadiusMode: node.openingRadiusMode ?? 'all',
openingCornerRadii: node.openingCornerRadii ?? [0.15, 0.15, 0.15, 0.15],
cornerRadius: node.cornerRadius,
archHeight: node.archHeight,
openingRevealRadius: node.openingRevealRadius,
columnRatios: node.columnRatios,
rowRatios: node.rowRatios,
columnDividerThickness: node.columnDividerThickness,
rowDividerThickness: node.rowDividerThickness,
sill: node.sill,
sillDepth: node.sillDepth,
sillThickness: node.sillThickness,
}
}, [node])
const handleSavePreset = useCallback(
async (name: string) => {
const data = getWindowPresetData()
if (!(data && selectedId)) return
const presetId = await adapter.savePreset('window', name, data)
if (presetId) emitter.emit('preset:generate-thumbnail', { presetId, nodeId: selectedId })
},
[getWindowPresetData, selectedId, adapter],
)
const handleOverwritePreset = useCallback(
async (id: string) => {
const data = getWindowPresetData()
if (!(data && selectedId)) return
await adapter.overwritePreset('window', id, data)
emitter.emit('preset:generate-thumbnail', { presetId: id, nodeId: selectedId })
},
[getWindowPresetData, selectedId, adapter],
)
const handleApplyPreset = useCallback(
(data: Record<string, unknown>) => {
handleUpdate(data as Partial<WindowNode>)
},
[handleUpdate],
)
if (!(node && node.type === 'window' && selectedId)) return null
const numCols = node.columnRatios.length
@@ -447,27 +386,6 @@ export default function WindowPanel() {
title={node.name || 'Window'}
width={320}
>
{/* Presets strip */}
<div className="border-border/30 border-b px-3 pt-2.5 pb-1.5">
<PresetsPopover
isAuthenticated={adapter.isAuthenticated}
onApply={handleApplyPreset}
onDelete={(id) => adapter.deletePreset(id)}
onFetchPresets={(tab) => adapter.fetchPresets('window', tab)}
onOverwrite={handleOverwritePreset}
onRename={(id, name) => adapter.renamePreset(id, name)}
onSave={handleSavePreset}
onToggleCommunity={adapter.togglePresetCommunity}
tabs={adapter.tabs}
type="window"
>
<button className="flex w-full items-center gap-2 rounded-lg border border-border/50 bg-[#2C2C2E] px-3 py-2 font-medium text-muted-foreground text-xs transition-colors hover:bg-[#3e3e3e] hover:text-foreground">
<BookMarked className="h-3.5 w-3.5 shrink-0" />
<span>Presets</span>
</button>
</PresetsPopover>
</div>
<PanelSection title="Type">
<SegmentedControl
onChange={(value) =>