perf(editor): convert UI icons from PNG to WebP
The editor's /icons assets were ~10MB of oversized PNGs (a single toolbar icon up to 1.4MB). Convert every non-PWA icon to WebP (quality 92) and repoint all /icons/*.png references to .webp across packages/editor, packages/nodes, and apps/editor. PWA/platform icons (apple-touch-icon, icon-192, icon-512) stay PNG. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5efcc834a8
commit
267dac7b1a
@@ -220,7 +220,7 @@ export const boxVentDefinition: NodeDefinition<typeof BoxVentNode> = {
|
||||
presentation: {
|
||||
label: 'Box Vent',
|
||||
description: 'Small louvered exhaust vent that sits on a roof slope.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 120,
|
||||
},
|
||||
|
||||
@@ -164,7 +164,7 @@ export default function BoxVentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Box Vent'}
|
||||
|
||||
@@ -50,7 +50,7 @@ export const buildingDefinition: NodeDefinition<typeof BuildingNode> = {
|
||||
presentation: {
|
||||
label: 'Building',
|
||||
description: 'A building container holding one or more levels.',
|
||||
icon: { kind: 'url', src: '/icons/building.png' },
|
||||
icon: { kind: 'url', src: '/icons/building.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 6,
|
||||
},
|
||||
|
||||
@@ -157,7 +157,7 @@ export const ceilingDefinition: NodeDefinition<typeof CeilingNode> = {
|
||||
presentation: {
|
||||
label: 'Ceiling',
|
||||
description: 'A polygon-bounded ceiling surface that hosts ceiling-mounted items.',
|
||||
icon: { kind: 'url', src: '/icons/ceiling.png' },
|
||||
icon: { kind: 'url', src: '/icons/ceiling.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 40,
|
||||
},
|
||||
|
||||
@@ -147,7 +147,7 @@ export function CeilingPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/ceiling.png"
|
||||
icon="/icons/ceiling.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Ceiling'}
|
||||
width={320}
|
||||
|
||||
@@ -409,7 +409,7 @@ export const chimneyDefinition: NodeDefinition<typeof ChimneyNode> = {
|
||||
presentation: {
|
||||
label: 'Chimney',
|
||||
description: 'Vertical masonry stack on a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 122,
|
||||
},
|
||||
|
||||
@@ -339,7 +339,7 @@ export default function ChimneyPanel() {
|
||||
// Match the current store node against the preset table so the
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Chimney'}
|
||||
|
||||
@@ -382,7 +382,7 @@ export const columnDefinition: NodeDefinition<typeof ColumnNode> = {
|
||||
presentation: {
|
||||
label: 'Column',
|
||||
description: 'A parametric column with configurable cross-section, base, and capital.',
|
||||
icon: { kind: 'url', src: '/icons/column.png' },
|
||||
icon: { kind: 'url', src: '/icons/column.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 70,
|
||||
},
|
||||
|
||||
@@ -313,7 +313,7 @@ export default function ColumnPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/column.png"
|
||||
icon="/icons/column.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Column'}
|
||||
width={300}
|
||||
|
||||
@@ -153,7 +153,7 @@ export const cupolaDefinition: NodeDefinition<typeof CupolaNode> = {
|
||||
presentation: {
|
||||
label: 'Cupola',
|
||||
description: 'Louvered roof lantern with a dome or pyramid cap and optional finial.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 122,
|
||||
},
|
||||
|
||||
@@ -137,7 +137,7 @@ export default function CupolaPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Cupola'}
|
||||
|
||||
@@ -251,7 +251,7 @@ export const doorDefinition: NodeDefinition<typeof DoorNode> = {
|
||||
presentation: {
|
||||
label: 'Door',
|
||||
description: 'A door cut into a wall. Animated open/close state.',
|
||||
icon: { kind: 'url', src: '/icons/door.png' },
|
||||
icon: { kind: 'url', src: '/icons/door.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 50,
|
||||
},
|
||||
|
||||
@@ -516,7 +516,7 @@ export default function DoorPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/door.png"
|
||||
icon="/icons/door.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Door'}
|
||||
width={320}
|
||||
|
||||
@@ -452,7 +452,7 @@ export const dormerDefinition: NodeDefinition<typeof DormerNode> = {
|
||||
presentation: {
|
||||
label: 'Dormer',
|
||||
description: 'House-shaped protrusion on a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 125,
|
||||
},
|
||||
|
||||
@@ -159,7 +159,7 @@ export default function DormerPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Dormer'}
|
||||
|
||||
@@ -197,7 +197,7 @@ export const downspoutDefinition: NodeDefinition<typeof DownspoutNode> = {
|
||||
presentation: {
|
||||
label: 'Downspout',
|
||||
description: 'Vertical drop pipe from a gutter outlet to the ground.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 123,
|
||||
},
|
||||
|
||||
@@ -122,7 +122,7 @@ export const ductFittingDefinition: NodeDefinition<typeof DuctFittingNode> = {
|
||||
presentation: {
|
||||
label: 'Duct Fitting',
|
||||
description: 'Elbow, tee, reducer, or square-to-round transition connecting duct runs.',
|
||||
icon: { kind: 'url', src: '/icons/duct-fitting.png' },
|
||||
icon: { kind: 'url', src: '/icons/duct-fitting.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 91,
|
||||
},
|
||||
|
||||
@@ -176,7 +176,7 @@ export const ductSegmentDefinition: NodeDefinition<typeof DuctSegmentNode> = {
|
||||
presentation: {
|
||||
label: 'Duct',
|
||||
description: 'HVAC duct run — polyline of round, rect, or flat-oval sections.',
|
||||
icon: { kind: 'url', src: '/icons/duct.png' },
|
||||
icon: { kind: 'url', src: '/icons/duct.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 90,
|
||||
},
|
||||
|
||||
@@ -89,7 +89,7 @@ export const ductTerminalDefinition: NodeDefinition<typeof DuctTerminalNode> = {
|
||||
label: 'Register',
|
||||
description:
|
||||
'Duct terminal — supply register, ceiling diffuser, or return grille. Duct runs end at its collar.',
|
||||
icon: { kind: 'url', src: '/icons/registers.png' },
|
||||
icon: { kind: 'url', src: '/icons/registers.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 93,
|
||||
},
|
||||
|
||||
@@ -256,7 +256,7 @@ export const elevatorDefinition: NodeDefinition<typeof ElevatorNode> = {
|
||||
presentation: {
|
||||
label: 'Elevator',
|
||||
description: 'A multi-level elevator shaft with configurable openings per level.',
|
||||
icon: { kind: 'url', src: '/icons/wallcut.png' },
|
||||
icon: { kind: 'url', src: '/icons/wallcut.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 80,
|
||||
},
|
||||
|
||||
@@ -471,7 +471,7 @@ export default function ElevatorPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/elevator.png"
|
||||
icon="/icons/elevator.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Elevator'}
|
||||
width={300}
|
||||
|
||||
@@ -160,7 +160,7 @@ export const eyebrowVentDefinition: NodeDefinition<typeof EyebrowVentNode> = {
|
||||
presentation: {
|
||||
label: 'Eyebrow Vent',
|
||||
description: 'Low curved lens-shaped roof vent with a louvered front.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 123,
|
||||
},
|
||||
|
||||
@@ -139,7 +139,7 @@ export default function EyebrowVentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Eyebrow Vent'}
|
||||
|
||||
@@ -230,7 +230,7 @@ export const fenceDefinition: NodeDefinition<typeof FenceNode> = {
|
||||
presentation: {
|
||||
label: 'Fence',
|
||||
description: 'A straight or curved fence segment with configurable posts and infill.',
|
||||
icon: { kind: 'url', src: '/icons/fence.png' },
|
||||
icon: { kind: 'url', src: '/icons/fence.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 20,
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@ export const guideDefinition: NodeDefinition<typeof GuideNode> = {
|
||||
presentation: {
|
||||
label: 'Guide',
|
||||
description: 'A measurement / reference annotation (linear, area, or arc).',
|
||||
icon: { kind: 'url', src: '/icons/blueprint.png' },
|
||||
icon: { kind: 'url', src: '/icons/blueprint.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 30,
|
||||
},
|
||||
|
||||
@@ -181,7 +181,7 @@ export const gutterDefinition: NodeDefinition<typeof GutterNode> = {
|
||||
presentation: {
|
||||
label: 'Gutter',
|
||||
description: 'Rain-water channel running along the eave of a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 122,
|
||||
},
|
||||
|
||||
@@ -94,7 +94,7 @@ export const hvacEquipmentDefinition: NodeDefinition<typeof HvacEquipmentNode> =
|
||||
label: 'HVAC Unit',
|
||||
description:
|
||||
'Furnace, air handler, or condenser — duct runs connect to its supply/return collars.',
|
||||
icon: { kind: 'url', src: '/icons/HVAC.png' },
|
||||
icon: { kind: 'url', src: '/icons/HVAC.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 92,
|
||||
},
|
||||
|
||||
@@ -320,7 +320,7 @@ export const itemDefinition: NodeDefinition<typeof ItemNode> = {
|
||||
presentation: {
|
||||
label: 'Item',
|
||||
description: 'A catalog-backed item (furniture, fixtures, decorations).',
|
||||
icon: { kind: 'url', src: '/icons/item.png' },
|
||||
icon: { kind: 'url', src: '/icons/item.webp' },
|
||||
paletteSection: 'furnish',
|
||||
paletteOrder: 10,
|
||||
},
|
||||
|
||||
@@ -100,7 +100,7 @@ export default function ItemPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon={node.asset.thumbnail || '/icons/furniture.png'}
|
||||
icon={node.asset.thumbnail || '/icons/furniture.webp'}
|
||||
onClose={handleClose}
|
||||
title={node.name || node.asset.name}
|
||||
width={300}
|
||||
|
||||
@@ -51,7 +51,7 @@ export const levelDefinition: NodeDefinition<typeof LevelNode> = {
|
||||
presentation: {
|
||||
label: 'Level',
|
||||
description: 'A single floor of a building, holding walls / slabs / ceilings / items.',
|
||||
icon: { kind: 'url', src: '/icons/level.png' },
|
||||
icon: { kind: 'url', src: '/icons/level.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 7,
|
||||
},
|
||||
|
||||
@@ -120,7 +120,7 @@ export const linesetDefinition: NodeDefinition<typeof LinesetNode> = {
|
||||
label: 'Lineset',
|
||||
description:
|
||||
'Refrigerant lineset — copper suction + liquid pair joining a condenser to the indoor coil.',
|
||||
icon: { kind: 'url', src: '/icons/lineset.png' },
|
||||
icon: { kind: 'url', src: '/icons/lineset.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 93,
|
||||
},
|
||||
|
||||
@@ -112,7 +112,7 @@ export const liquidLineDefinition: NodeDefinition<typeof LiquidLineNode> = {
|
||||
label: 'Liquid Line',
|
||||
description:
|
||||
'Standalone refrigerant liquid line — a thin bare-copper run; Follow mode traces an existing lineset.',
|
||||
icon: { kind: 'url', src: '/icons/lineset.png' },
|
||||
icon: { kind: 'url', src: '/icons/lineset.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 94,
|
||||
},
|
||||
|
||||
@@ -93,7 +93,7 @@ export const pipeFittingDefinition: NodeDefinition<typeof PipeFittingNode> = {
|
||||
label: 'Pipe Fitting',
|
||||
description: 'DWV joint — elbow bend, 45° wye, or sanitary tee.',
|
||||
// Reuses the duct-fitting artwork — DWV fittings read the same in the UI.
|
||||
icon: { kind: 'url', src: '/icons/duct-fitting.png' },
|
||||
icon: { kind: 'url', src: '/icons/duct-fitting.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 96,
|
||||
hidden: true,
|
||||
|
||||
@@ -118,7 +118,7 @@ export const pipeSegmentDefinition: NodeDefinition<typeof PipeSegmentNode> = {
|
||||
label: 'DWV Pipe',
|
||||
description:
|
||||
'Drain / waste / vent pipe run — waste lines fall at ¼″ per foot, vents run level or vertical.',
|
||||
icon: { kind: 'url', src: '/icons/dwv-pipes.png' },
|
||||
icon: { kind: 'url', src: '/icons/dwv-pipes.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 95,
|
||||
},
|
||||
|
||||
@@ -205,7 +205,7 @@ export const ridgeVentDefinition: NodeDefinition<typeof RidgeVentNode> = {
|
||||
presentation: {
|
||||
label: 'Ridge Vent',
|
||||
description: 'Ventilation strip running along the ridge of a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 121,
|
||||
},
|
||||
|
||||
@@ -128,7 +128,7 @@ export default function RidgeVentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Ridge Vent'}
|
||||
|
||||
@@ -313,7 +313,7 @@ export const roofSegmentDefinition: NodeDefinition<typeof RoofSegmentNode> = {
|
||||
presentation: {
|
||||
label: 'Roof Segment',
|
||||
description: 'A single pitched plane of a parent roof.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 101,
|
||||
},
|
||||
|
||||
@@ -121,7 +121,7 @@ export default function RoofSegmentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={handleBack}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Roof Segment'}
|
||||
|
||||
@@ -179,7 +179,7 @@ export const roofDefinition: NodeDefinition<typeof RoofNode> = {
|
||||
presentation: {
|
||||
label: 'Roof',
|
||||
description: 'A pitched / hip / gable roof composed of one or more segments.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 100,
|
||||
},
|
||||
|
||||
@@ -249,7 +249,7 @@ export default function RoofPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Roof'}
|
||||
width={300}
|
||||
|
||||
@@ -42,7 +42,7 @@ export const scanDefinition: NodeDefinition<typeof ScanNode> = {
|
||||
presentation: {
|
||||
label: 'Scan',
|
||||
description: 'A captured mesh (LiDAR / photogrammetry) imported as a scene reference.',
|
||||
icon: { kind: 'url', src: '/icons/mesh.png' },
|
||||
icon: { kind: 'url', src: '/icons/mesh.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 40,
|
||||
},
|
||||
|
||||
@@ -265,7 +265,7 @@ export const shelfDefinition: NodeDefinition<typeof ShelfNode> = {
|
||||
presentation: {
|
||||
label: 'Shelf',
|
||||
description: 'A configurable shelving unit. Items host on each row.',
|
||||
icon: { kind: 'url', src: '/icons/shelf.png' },
|
||||
icon: { kind: 'url', src: '/icons/shelf.webp' },
|
||||
paletteSection: 'furnish',
|
||||
paletteOrder: 30,
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ export const siteDefinition: NodeDefinition<typeof SiteNode> = {
|
||||
presentation: {
|
||||
label: 'Site',
|
||||
description: 'The top-level container holding buildings, zones, and the property boundary.',
|
||||
icon: { kind: 'url', src: '/icons/site-flag.png' },
|
||||
icon: { kind: 'url', src: '/icons/site-flag.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 5,
|
||||
},
|
||||
|
||||
@@ -271,7 +271,7 @@ export const skylightDefinition: NodeDefinition<typeof SkylightNode> = {
|
||||
presentation: {
|
||||
label: 'Skylight',
|
||||
description: 'Framed glass opening on a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 124,
|
||||
},
|
||||
|
||||
@@ -258,7 +258,7 @@ export default function SkylightPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Skylight'}
|
||||
|
||||
@@ -208,7 +208,7 @@ export const slabDefinition: NodeDefinition<typeof SlabNode> = {
|
||||
presentation: {
|
||||
label: 'Slab',
|
||||
description: 'A polygon-bounded floor surface that hosts items on top.',
|
||||
icon: { kind: 'url', src: '/icons/floor.png' },
|
||||
icon: { kind: 'url', src: '/icons/floor.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 30,
|
||||
},
|
||||
|
||||
@@ -152,7 +152,7 @@ export function SlabPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/floor.png"
|
||||
icon="/icons/floor.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Slab'}
|
||||
width={320}
|
||||
|
||||
@@ -272,7 +272,7 @@ export const solarPanelDefinition: NodeDefinition<typeof SolarPanelNode> = {
|
||||
presentation: {
|
||||
label: 'Solar Panel',
|
||||
description: 'Grid of photovoltaic panels mounted on a roof segment.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 123,
|
||||
},
|
||||
|
||||
@@ -181,7 +181,7 @@ export default function SolarPanelPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Solar Panel'}
|
||||
|
||||
@@ -107,7 +107,7 @@ export const spawnDefinition: NodeDefinition<typeof SpawnNode> = {
|
||||
presentation: {
|
||||
label: 'Spawn Point',
|
||||
description: 'Player or camera origin within a level. One per level.',
|
||||
icon: { kind: 'url', src: '/icons/spawn-point.png' },
|
||||
icon: { kind: 'url', src: '/icons/spawn-point.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 90, // bottom of structure list — matches legacy palette order
|
||||
},
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function SpawnPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/spawn-point.png"
|
||||
icon="/icons/spawn-point.webp"
|
||||
onClose={handleClose}
|
||||
title="Spawn Point"
|
||||
width={300}
|
||||
|
||||
@@ -140,7 +140,7 @@ export const stairSegmentDefinition: NodeDefinition<typeof StairSegmentNode> = {
|
||||
presentation: {
|
||||
label: 'Stair Segment',
|
||||
description: 'A single flight of a parent stair.',
|
||||
icon: { kind: 'url', src: '/icons/stairs.png' },
|
||||
icon: { kind: 'url', src: '/icons/stairs.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 111,
|
||||
},
|
||||
|
||||
@@ -121,7 +121,7 @@ export default function StairSegmentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/stairs.png"
|
||||
icon="/icons/stairs.webp"
|
||||
onBack={handleBack}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Stair Segment'}
|
||||
|
||||
@@ -496,7 +496,7 @@ export const stairDefinition: NodeDefinition<typeof StairNode> = {
|
||||
label: 'Stair',
|
||||
description:
|
||||
'A stair composed of one or more flights with configurable treads, risers, railings.',
|
||||
icon: { kind: 'url', src: '/icons/stairs.png' },
|
||||
icon: { kind: 'url', src: '/icons/stairs.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 110,
|
||||
},
|
||||
|
||||
@@ -226,7 +226,7 @@ export default function StairPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/stairs.png"
|
||||
icon="/icons/stairs.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Staircase'}
|
||||
width={300}
|
||||
|
||||
@@ -126,7 +126,7 @@ export const turbineVentDefinition: NodeDefinition<typeof TurbineVentNode> = {
|
||||
presentation: {
|
||||
label: 'Turbine Vent',
|
||||
description: 'Wind-driven spinning whirlybird exhaust vent for a roof slope.',
|
||||
icon: { kind: 'url', src: '/icons/roof.png' },
|
||||
icon: { kind: 'url', src: '/icons/roof.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 121,
|
||||
},
|
||||
|
||||
@@ -161,7 +161,7 @@ export default function TurbineVentPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/roof.png"
|
||||
icon="/icons/roof.webp"
|
||||
onBack={node.roofSegmentId ? handleBack : undefined}
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Turbine Vent'}
|
||||
|
||||
@@ -115,7 +115,7 @@ export const wallDefinition: NodeDefinition<typeof WallNode> = {
|
||||
presentation: {
|
||||
label: 'Wall',
|
||||
description: 'A straight or curved wall segment. Hosts doors, windows, and wall-mounted items.',
|
||||
icon: { kind: 'url', src: '/icons/wall.png' },
|
||||
icon: { kind: 'url', src: '/icons/wall.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 10,
|
||||
},
|
||||
|
||||
@@ -137,7 +137,7 @@ export default function WallPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/wall.png"
|
||||
icon="/icons/wall.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Wall'}
|
||||
width={280}
|
||||
|
||||
@@ -229,7 +229,7 @@ export const windowDefinition: NodeDefinition<typeof WindowNode> = {
|
||||
presentation: {
|
||||
label: 'Window',
|
||||
description: 'A window cut into a wall. Animated open/close for opening windows.',
|
||||
icon: { kind: 'url', src: '/icons/window.png' },
|
||||
icon: { kind: 'url', src: '/icons/window.webp' },
|
||||
paletteSection: 'structure',
|
||||
paletteOrder: 60,
|
||||
},
|
||||
|
||||
@@ -383,7 +383,7 @@ export default function WindowPanel() {
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
icon="/icons/window.png"
|
||||
icon="/icons/window.webp"
|
||||
onClose={handleClose}
|
||||
title={node.name || 'Window'}
|
||||
width={320}
|
||||
|
||||
@@ -66,7 +66,7 @@ export const zoneDefinition: NodeDefinition<typeof ZoneNode> = {
|
||||
presentation: {
|
||||
label: 'Zone',
|
||||
description: 'A polygonal site zone (lawn, water, paving) with a TSL gradient material.',
|
||||
icon: { kind: 'url', src: '/icons/zone.png' },
|
||||
icon: { kind: 'url', src: '/icons/zone.webp' },
|
||||
paletteSection: 'site',
|
||||
paletteOrder: 20,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user