package cc.unitmesh.xuiper.render.stateful import cc.unitmesh.xuiper.ir.NanoActionIR import cc.unitmesh.xuiper.ir.NanoIR /** * NanoNodeRegistry - Component registry and dispatcher * * Manages the mapping from component type to renderer. * Platform implementations register their renderers here. * * Design goals: * - Type-safe registration of renderers * - Fallback handling for unknown components * - Easy extension for new component types * - Reusable across platforms (Compose, Jewel, HTML, etc.) * * Example usage: * ```kotlin * // Create registry with builder DSL * val registry = NanoNodeRegistry.build Unit> { * register("Text") { ctx -> { Text(ctx.node.stringProp("content") ?: "") } } * register("VStack") { ctx -> { Column { ctx.renderChildren().forEach { it() } } } } * fallback { ctx -> { Text("Unknown: ${ctx.node.type}") } } * } * * // Or use the map-based constructor * val registry = NanoNodeRegistry( * renderers = mapOf( * "Text" to textRenderer, * "VStack" to vstackRenderer * ), * fallbackRenderer = unknownRenderer * ) * ``` */ class NanoNodeRegistry( private val renderers: Map>, private val fallbackRenderer: NanoNodeRenderer ) { /** * Get renderer for a component type. * Returns fallback renderer if type is not registered. */ fun getRenderer(type: String): NanoNodeRenderer { return renderers[type] ?: fallbackRenderer } /** * Check if a renderer is registered for a type. */ fun hasRenderer(type: String): Boolean = type in renderers /** * Get all registered component types. */ fun registeredTypes(): Set = renderers.keys /** * Create a new registry with additional renderers. */ fun extend(additionalRenderers: Map>): NanoNodeRegistry { return NanoNodeRegistry(renderers + additionalRenderers, fallbackRenderer) } /** * Create a new registry with a different fallback renderer. */ fun withFallback(newFallback: NanoNodeRenderer): NanoNodeRegistry { return NanoNodeRegistry(renderers, newFallback) } companion object { /** * Build a registry using DSL. */ fun build(block: RegistryBuilder.() -> Unit): NanoNodeRegistry { val builder = RegistryBuilder() builder.block() return builder.build() } } } /** * Builder for NanoNodeRegistry with DSL support. */ class RegistryBuilder { private val renderers = mutableMapOf>() private var fallbackRenderer: NanoNodeRenderer? = null /** * Register a renderer for a component type. */ fun register(type: String, renderer: NanoNodeRenderer) { renderers[type] = renderer } /** * Register multiple renderers at once. */ fun registerAll(vararg pairs: Pair>) { pairs.forEach { (type, renderer) -> renderers[type] = renderer } } /** * Set the fallback renderer for unknown component types. */ fun fallback(renderer: NanoNodeRenderer) { fallbackRenderer = renderer } internal fun build(): NanoNodeRegistry { val fb = fallbackRenderer ?: throw IllegalStateException("Fallback renderer must be set") return NanoNodeRegistry(renderers.toMap(), fb) } } /** * Extension function to create a dispatcher from a registry. */ fun NanoNodeRegistry.toDispatcher(): StatefulNanoNodeDispatcher { return StatefulNanoNodeDispatcher(this) }