Add Presentation + IconRef to NodeDefinition v1 surface

Adds optional `presentation` field for tool palette metadata: sentence-
case label, optional description, icon (iconify reference, inline SVG,
or lazy React component), palette section override, sort order, and a
`hidden` flag for container kinds that exist but should not appear in
the palette.

Consumer arrives in Phase 4 (auto-derived palette buttons) — defining
the type now means Phase 2's `column` and `shelf` definitions ship with
the field already populated, no later round-trip.

Iconify is the encouraged form for built-ins and AI-authored nodes:
matches the @iconify-react setup the editor app already uses, and AI
emits a name string from a curated list (no asset upload step needed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Wassim SAMAD
2026-05-14 12:09:10 -04:00
co-authored by Claude Opus 4.7
parent c683c04c39
commit 3de098fe4f
2 changed files with 38 additions and 0 deletions
+2
View File
@@ -10,6 +10,7 @@ export type {
DragAction, DragAction,
EditorCtx, EditorCtx,
HostableConfig, HostableConfig,
IconRef,
Issue, Issue,
LazyComponent, LazyComponent,
McpOverrides, McpOverrides,
@@ -22,6 +23,7 @@ export type {
ParamField, ParamField,
ParamGroup, ParamGroup,
Plugin, Plugin,
Presentation,
Relations, Relations,
RendererSource, RendererSource,
RotatableConfig, RotatableConfig,
+36
View File
@@ -32,11 +32,47 @@ export type NodeDefinition<S extends ZodObject<any>> = {
tool?: LazyComponent tool?: LazyComponent
affordances?: Affordance<z.infer<S>>[] affordances?: Affordance<z.infer<S>>[]
presentation?: Presentation
mcp?: McpOverrides mcp?: McpOverrides
} }
export type NodeCategory = 'site' | 'structure' | 'furnish' | 'analysis' | 'utility' export type NodeCategory = 'site' | 'structure' | 'furnish' | 'analysis' | 'utility'
// ─── Presentation (tool palette + UI surface) ────────────────────────
/**
* UI metadata for surfacing a node kind in the tool palette and elsewhere.
* Phase 4 ships the consumer (auto-derived palette buttons); definitions can
* declare this from Phase 2 onward so the spike's `column` and `shelf` show up
* correctly the moment the palette consumes the registry.
*/
export type Presentation = {
/** Sentence-case label shown in palette buttons, breadcrumbs, etc. */
label: string
/** Optional longer tooltip / help text. */
description?: string
/** Icon for palette buttons and tree views. */
icon: IconRef
/** Tool palette section. Defaults to `category` when omitted. */
paletteSection?: 'site' | 'structure' | 'furnish'
/** Sort key within a palette section; lower numbers come first. */
paletteOrder?: number
/** Set true for kinds that exist but should NOT appear in the palette
* (containers like `site`/`building`/`level`, internal nodes). */
hidden?: boolean
}
export type IconRef =
/** Iconify identifier, e.g. `lucide:square`. Matches the @iconify-react
* setup the editor app already uses for tool icons. */
| { kind: 'iconify'; name: string }
/** Inline SVG path data. Use for asset packs or plugins that want a custom
* mark without contributing a React component. */
| { kind: 'svg'; viewBox: string; path: string }
/** Custom React component, lazy-loaded. Use sparingly — adds a Suspense
* boundary per icon. */
| { kind: 'component'; module: () => Promise<{ default: ComponentType }> }
export type LazyComponent = () => Promise<{ default: ComponentType }> export type LazyComponent = () => Promise<{ default: ComponentType }>
export type RendererSource<N> = export type RendererSource<N> =