feat(editor): preset-system polish — paint panel, slim action bar, icon rail (#354)

* feat(editor): preset-system polish — paint panel, slim action bar, icon rail

- Export `MaterialPaintPanel` so embedders host the paint material picker in
  their own panel (community docks it in the Build sidebar) instead of the
  bottom action bar.
- ActionMenu: drop the build / material-paint / furnish modes and the
  structure-tools palette row + paint tray (the host's Build sidebar owns
  building now). Reduce `structure-tools` to the shared `tools` lookup still
  used by cursor/floorplan indicators; remove the orphaned `useContextualTools`.
- MaterialPicker: swatches wrap into a fluid `auto-fill` grid that fills width.
- IconRail (tab-bar): bigger icons, grayscale-when-idle, Radix tooltip, w-14
  rail; sync `RAIL_WIDTH` to 56.
- Inspector footer: hand the host `footer` to kind-owned custom panels via
  `InspectorFooterContext` so the save button renders without per-kind wiring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: biome format pass

Whole-repo formatter normalization (line wrap/unwrap only, no logic changes)
surfaced by the format-on-edit hook against prior drift. Kept separate from the
feature commit so the preset-system diff stays reviewable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-06-01 13:13:23 -04:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 891e578481
commit 8abfc94b99
40 changed files with 188 additions and 550 deletions
+4 -15
View File
@@ -154,20 +154,14 @@ function columnBraceHandle(axis: 'x' | 'z'): HandleDescriptor<ColumnNodeType> {
axis,
anchor: 'center',
min: MIN_BRACE_DIMENSION,
currentValue: (n) =>
axis === 'x' ? (n.braceWidth ?? n.width) : (n.braceDepth ?? n.depth),
apply: (_n, newValue) =>
axis === 'x' ? { braceWidth: newValue } : { braceDepth: newValue },
currentValue: (n) => (axis === 'x' ? (n.braceWidth ?? n.width) : (n.braceDepth ?? n.depth)),
apply: (_n, newValue) => (axis === 'x' ? { braceWidth: newValue } : { braceDepth: newValue }),
placement: {
position: (n) => {
// Position outside any splay so the arrow clears the legs.
const half =
axis === 'x'
? Math.max(
n.braceBottomSpread ?? 0,
n.braceTopSpread ?? 0,
n.braceWidth ?? n.width,
) / 2
? Math.max(n.braceBottomSpread ?? 0, n.braceTopSpread ?? 0, n.braceWidth ?? n.width) / 2
: (n.braceDepth ?? n.depth) / 2
return axis === 'x'
? [half + BRACE_HANDLE_OFFSET, n.height / 2, 0]
@@ -205,12 +199,7 @@ function columnFootprintHalf(n: ColumnNodeType): { halfX: number; halfZ: number
}
return {
halfX:
Math.max(
n.width,
n.braceWidth ?? 0,
n.braceBottomSpread ?? 0,
n.braceTopSpread ?? 0,
) / 2,
Math.max(n.width, n.braceWidth ?? 0, n.braceBottomSpread ?? 0, n.braceTopSpread ?? 0) / 2,
halfZ: Math.max(n.depth, n.braceDepth ?? 0) / 2,
}
}